Phew! Finally got it to work. For some reason on my end, using a W7 installed machine it worked with Python. You didn't have to have to go through those extra miles in explaining, but you did. Really appreciate your time for doing all of this for us. As for me, you'll always get 2 thumbs up.
For everyone who is struggling with the chrome browser not being able to access files from your file explorer and don't want to install a server, here are the simple steps you need to follow: 1. Close all instances(tabs and windows) of the browser. 2. Open Task Manager and make sure no Chrome processes are running (Chrome extensions can still be running). If any processes are running then end them. 3. Open cmd prompt and navigate to the directory where chrome is installed. Example: cd "C:\Program Files (x86)\Google\Chrome\Application" 4. Start chrome from within the cmd prompt using --allow-file-access-from-files option. Example: start chrome.exe --allow-file-access-from-files 5. Now drag and drop the .html file to this window and you should be able to see the textured cube. To avoid typing lines in cmd prompt all the time, I created a batch file. FileName: open-chrome-withfileaccess.bat Content: cd "C:\Program Files (x86)\Google\Chrome\Application" start chrome.exe --allow-file-access-from-files exit Now just execute the batch file to launch the browser with the said option.
Tip: You can hide an HTML element (like that image) just by adding the word "hidden" to the image tag. For example: You don't need to set the width and height to zero :)
Heads up for anyone using a larger texture (or if it only works some of the time). Adding a small delay on the Init function lets the texture load before texImage2D gets it. Something like setTimeout(function() {Init();}, 100); gives it 100ms to load. 10ms is the minimum, which works for most small textures.
Another quality tutorial fella! Quick note - if anyone is having issues with http-server caching, this may sort your problem 'http-server -c-1 -a localhost -p 8000'
My burning question is why do we bind and set the active texture in the main render loop if it isn't changing (at least in this example)? Surely we could move these in front of the loop and be okay, right?
For some reason, I didn’t get the security issue on Google Chrome on my Mac. Maybe the extra security from the Mac allowed me to bypass the security error.
23:20 doesn't work with Python3, but there's an easy fix. python -m SimpleHTTPServer returns an error saying No module named SimpleHTTPServer Instead, try python3 -m http.server or python -m http.server if you have Python3 Then search for localhost:8000 in your browser.
Glad you enjoyed it! Yes, there absolutely is. For a cube, you can split the input texture into some sort of grid, and put the image for each face in a separate cell - for example, the top face is in the top-left third of your texture, forward face in the top-middle, etc. Instead of using UV coordinates (0,1) on each side of the cube, you might use (0, 0.333) UV for the top, (0.333, 0.6667) U and (0, 0.3333) V for the front, etc. You can do all sorts of clever things with elaborate character models and textures, the subject to look more into is "texture mapping." The hard part of doing that lies on the artist creating the texture and model. I'm not very good at modeling or texturing so I can't say much more than that, but it is an interesting study with a lot of great resources out there.
hi. First of all thanks your video. it is very helpful. But I have Problem. I use vue.js. I coded what you coded. İt works. but I refresh the page, image did not come. I went to another page and return my webgl cube page, image run. When I every refresh my website, image does not come at fisrt time. What is problem ?
Hmm... I don't know offhand what the problem is, I'd have to see the code - I'm not familiar with Vue.js, but that sounds to me like a DOM lifecycle thing? Or maybe a change detection issue. Maybe your WebGL code is running before the DOM has been placed? Or Vue is swapping out the canvas after your WebGL code runs, and then not re-running your WebGL code? I'm not sure - I'd guess it's a lifecycle thing, but don't know.
Hmm, tricky... I've had an issue when using `python -m SimpleHTTPServer` with loading some files, I don't really know why but using the NPM http-server instead (www.npmjs.com/package/http-server) has fixed it for me. If it's a cache thing, you can disable the cache while developing by keeping the developer tools open (Firefox and Chrome, probably Edge/IE/Safari too but I haven't checked). F12 to open the dev tools, there's a setting (usually "Disable Cache") that you can enable, that'll keep the cache turned off. If you go to the network tab in the developer tools (F12 usually) and load the page, does it look like the image loads? There'll be a list of files that are loaded with the webpage along with the status codes, types, etc. The image you load should come back with a 200 code. If it doesn't the first time, but does afterwards, then it's a problem with whatever server you're using. If it does come back with a 200 the first time but doesn't show anything, disabling the cache should fix it - though that only helps you (it doesn't help if you're trying to show other people).
Thanks for the video. It was very informative. I did, however, run into an error that I couldn't fix unless I switched browsers. Up until the point where you open the server everything was working fine on Chrome, but upon trying to run on the server I got the error : Failed to execute 'texImage2D' on 'WebGLRenderingContext': No function was found that matched the signature provided. at InitApp (app.js:229) Switching over to Edge made it work fine, but I couldn't find any way to make it run on Chrome.
Hmm.... Interesting, that's a WebGL standard call, it should work well between all the browsers. Thanks for the heads up! It's possible I called it in a non-standard way somehow (though I tried to scrub all of my API calls to make sure they were correct) and that Chrome caught it while the other browsers ignored the errors or something. I'm glad you enjoyed the video, sorry you ran into a problem while running the code!
Hmm.... that sounds like a texture issue, check the console for warnings - browsers usually do an okay-ish job of putting WebGL errors there. Unfortunately it's really tricky to debug WebGL issues like that - Edge is usually pretty good in my experience, but there are weird things here and there.
Thanks! Good question, it doesn't need to be there. You only need to swap out texture bindings when the texture itself changes - in this tutorial, it never does, so putting the binding inside the render loop is unnecessary. It's been a long time since I wrote these, but I'd guess that I probably put it there to explicitly specify the texture near the code that also specifies other properties of the object in that frame (matWorld, matView, matProj). When rendering many objects with different textures, you'll need to swap them out in the render loop before using the desired texture - in those cases I like to keep texture binding somewhat near binding other properties, unless I'm able to batch the calls to avoid repeated texture updates.
at approx 13:07, not every U, V number corresponds to the pattern of -1 = 0 and 1 = 1. As you go into the Left section, and Right and so on the pattern seems random to me. Can you explain why that is?
Yeah, it's a funky pattern. The XYZ part of the vertices represent the 3D position of the vertex. Each segment of four vertices forms one face of the box - labeled by the comments (Top, Left, Right, Front, Back, Bottom). Each side will have a full version of the image, which is a square that is formed by the UV coordinates , , and . For each side of the cube, I picked a vertex to be the lower left part of the image, one for the upper left, etc. For this symmetric image, it didn't really matter which I picked, so long as upper-left and lower-right were always diagonal, and same for upper-right and lower-left.
What if I want to use different textures with different sides of the cube? Do I have to draw one side, then call bindTexture activeTexture, then draw another side and so on?
That's one option. You can also use different texture coordinates for each side, pointing to different parts of the texture, and put pictures of the different sides together in the same image. There's six sides of a cube, if you split an image 3x3 into smaller squares you can fit all six sides into it, and have three squares empty. You can also use a cube map in some circumstances, though I think that's more commonly used for reflections and skyboxes (probably a performance reason).
Hey, I don't know if you are still active but by any chance could you tell me how to place a texture onto a rectangle in stead of a cube. The texture comes in the form of an ImageBitmap. Thanks in advance. :)
So if I want to draw a rectange and an image, do I need two different shaders? Does it make everything slower? Is it possible to merge the two shaders into one shader?
Great questions, and the answer to all of them is "it depends". It takes time to switch shaders. Not a long time though, so it's usually worthwhile to have different shaders to do different effects if one effect is much slower than the other - you make up the time you lose switching shaders by saving time on drawing all those pixels at a lower cost. If you wanted a rectangle that was a solid color and a cube, you could take a small image (1px) of the color you want to use for the rectangle, and still use the same shader for both. Or you could write two different shaders (one to use textures, the other solid colors). I don't think there would be a huge difference in speed, but I would guess using the same shader would be faster. But say you wanted to make a scene with a lot of cartoon-y, flat shaded objects like this crate, but also some metalic, shiny rocks (Breath of the Wild does this a lot, it's a neat style). Reflections and shininess are much more expensive to calculate than flat colored objects - you could use the same shader for both by using a texture to represent the shininess of an object and just passing in a plain black texture for the cartoon-y objects, but you'd be much better off using two shaders to avoid having to do the extra (expensive) lighting calculations and texture sampling on most of the objects in your scene. It is possible, but almost never necessary to merge multiple shading styles into one shader - have something like "if (isShader1) { ... do first shader logic ... } else if (isShader2) {...}". If your GPU batches any fragment executions for the more expensive branch with a large batch of cheap fragments, then all the cheap fragments still have to wait for the small group of expensive ones to finish. Plus, writing complex shaders is a huge pain to debug. The only time I can think when you'd want to combine many shaders into one is if you're writing a shader to do raytracing without using a realtime raytracing API (DirectX 12, Vulkan) for a small area of the scene - metaballs is a great example of this. In that case, you'd have to have multiple shader functions all in the same shader file, because that hack to get raytracing works requires you to draw a single flat square covering the entire area where all of the raytraced objects might be drawn and do some clever math to actually perform the raytracing.
That all said, unless you're writing a ton of frivolous shaders, you probably won't notice a performance hit - especially if you're careful to only switch them when necessary (batch together your render calls to draw all things with shader1 before switching to shader2, etc).
@@IndigoCode Thanks for your reply! Never thought of using 1x1 images. But now I've settled and am using multiple shaders for different needs. Yeah, I think I'll batch render calls and draw stuff in order according to the shader it is using. I am making a little "engine" for drawing graphics for fun, currently it just has a viewport and all these functions you usually can access via the 2D context. Again, thanks a lot for that valuable piece of advice.
That sounds like you're running your page by just opening up the file in a browser - so the URL bar will show something like "file:///..." There is a security policy in place that prevents you from running GLSL code or using images that comes from a different website, or "cross-origin." To fix this, you'll need to use a local webserver. If you have PHP installed, put it under your "www" directory and use the URL "localhost" If you have Python installed, use the command "python -m SimpeHTTPServer" while in the directory of your project, and go to "localhost:8080" You can put that command in a file called "server.bat" and run it if you don't want to mess with the command line yourself. If you have NPM installed, there's a simple server you can install with "npm install -g http-server", after which you can run the command "http-server" and go to "localhost:3000". Same as with the python instructions, you can put thatcommand in a "server.bat" and run it by double-clicking if you don't want to mess with the command line.
To be honest, this whole requiring a server thing feels more like an attempt to inconvenience developers and push all web applications to be purely cloud-based, and potentially enforce always-on DRM... cross-origin also won't explicitly stop malicious code from executing, it just means the hackers will put the code/viruses somewhere in such a way it doesn't break cross-origin policy. Meanwhile, the days of the local web app and testing web apps locally is gone. I also feel these 'easy' server packages are quite the contrary... It should be solely up to the user to allow/deny applications to access local files, especially local applications. something that's actually HOSTED online is one thing. And as for protecting assets from your server from being grabbed, honestly, server owners should configure their own servers to allow/deny access to stuff. A majority do not, and that's their choice/problem. The malicious code side, hard to say. But the problem doesn't exist solely in cross-site code execution/injection, but also in the fact there was an underlying security exploit, already. If cross-origin resource policy is to protect the client side, it fails gravely. Hackers will just upload their malicious code to their own site (or break into someone else's) and execute it that way. From the side of protecting the assets on your site from being used/lifted by another, you really should have the site set-up as such it's very hard to do in the first place. The number of implications it could have on a whole variety of web applications and entire sites is immense, especially if it were to be brought to its truest form, which is to block EVERYTHING that came from "cross-origin"... Of course, there's currently a double-standard on what it impacts, so... No offense to you if you DO believe in this, but I don't, and it would be very hard to convince me otherwise. Seems to me more like an excuse to avoid fixing (or testing for) the underlying security issues that allow XSS to even WORK, or for site owners/admins having to avoid learning how to PROPERLY protect their system and/or resources, all of this at the expense of the the users and developers that just want the content they're trying to view or create to even WORK. Thanks for these tutorials, they are well-made and informative. I'm also curious, how would the cross-origin problems affect something that was generated by code (thus has no origin besides the memory) , or was embedded into the scripts/HTML directly via text-based encoding systems like base64? And just for kicks, the file upload tag/system? Also, I also cannot think of any examples, but iirc, it IS possible to put malicious code on the GPU, and the effects of the GPU seriously failing are often crippling/fatal to the impacted device. But, I don't see how cross-origin policy can possibly mitigate that. Just means if I were a hacker that knows how to put malware in the GPU, I'd put my bad on my own site, and draw my poor victims in with something like "Play MineCraft Online, for FREE, no account/registration needed!" then, BAM! Their computers crash/die. It IS possible to append other data to a file, like a PNG image, but really, the programs that are reading those should be designed to detect that. I did read about a Java exploit that used such an approach. Again, the plugin should've been checking there's not a .jar attached/embedded to another file, which was addressed eventually. JS and others have numerous exploits that don't rely on XSS and similar, though. I seriously HOPE webGL has the necessary levels of security and even error-checking to prevent doing something that kills the computer and/or GPU, regardless of what method is used to introduce it. Writing Assembly or C is dangerous for more or less the same reasons.
Are you asking about adding an image on top of the texture (like adding a sticker onto the crate texture)? You can do this by editing the texture image using an image editor like GIMP, Paint, or Photoshop.
Hi. I got an error "WebGL: INVALID_VALUE: texImage2D: no image data" even when I copy/pasted your code. Still, your online demo works fine. I am using python SimpleHTTPServer. What could the problem be?
Hi! So, it's impossible for me to know for certain what the problem is (since I can't see your code and the error), but I think I know what the problem is. The most likely issue is that your code is failing to pick up the Image object - try running document.getElementById('crate-image') in the console. It should give result of an tag. If you get 'null' instead, check your HTML code and make sure you have this line of code in there: . If you copied and pasted the code, there shouldn't be any typos in 'crate-image' in either the JavaScript or HTML code, but that's another place I'd look. If you do get the tag in the console, it's possible that the script is executing before the image is loading. To fix that, just make sure that the tags for loading app.js come in the body after the tag loading the image. This will prevent app.js from executing until the image is done loading. While much less likely, there are some other things that cause an INVALID_VALUE error to be raised: If width or height is negative, if the image is bigger than the maximum texture size your GPU can support (which it isn't, if you can run the online demo), or some things involving cube mapping (which we're not doing here). There's a whole list of what that particular error can mean here: msdn.microsoft.com/en-us/library/dn302435(v=vs.85).aspx
I got an error "INVALID_VALUE: texImage2D: width or height out of range" when i copied the source code. The error is in this code: gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, document.getElementById('crate-image') );
(1) Check to see if the image is being loaded by the page at all - in the developer tools for all browsers that I know of, there's a `network` tab. You can look in there to see if the image gets loaded, or if there's a 404. If it's not loaded, check the path you use to reference the image, and make sure the image is in the right place in the folder you're serving. (2) If all that is good, make sure there's no WebGL warnings in the console. It's possible you missed a parameter on loading the image. (3) Check your buffers to make sure you're sending over UV data, and make sure you're setting the vertex attributes correctly. If you followed the code, you should have that.
Hmm... That's odd. WebGL should be able to handle any HTMLImageElement that can be processed by the browser - check the JavaScript console for warnings/errors, there's a bunch of things around textures that can go wrong (image format, non power of two textures, cross-domain request) Firefox is usually better at reporting WebGL warnings, though anything that causes problems to happen should be reported by Chrome too.
Yeah... For awhile, the first several videos had almost exactly half as many as the one before. I figure they're pretty long videos, and it's easier to figure things out once you've learned the fundamentals (less need for later videos). Still a lot more views on all of them than I ever expected when I made them though :-)
My guess is that people click on the first video thinking it's easy, then when they realise the reality, they slowly drop out one by one. A bit sad really. I don't understand 50% of what I'm writing in these tutorials, but when finished I hope to do my own research and figure out what does what and how to do more complicated and fun things with it.
@@Rocco-tb9ih I can see how it seems sad, but the way I see it, I think it's good that video tutorials like this one help viewers get an idea of whether or not WebGL coding is right for them. They may have stopped watching after the first video, not because they "gave up", but because the first video gave them enough info to decide they would rather not pursue WebGL.
@@911WasActuallyBears That depends on what method of antialiasing one uses. You're right that anti-aliasing _alone_ doesn't solve the problem, and that it can even make it worse. Anti-aliasing with sub-pixel multisampling, on the other hand… ;J
lol. i see you everywhere!! ah back too simple c/c++ huh?? i honestly have yet to see what is so much easier about these "modern" and "cool" and "easy" languages. quiet honestly they are much worst.
Phew! Finally got it to work. For some reason on my end, using a W7 installed machine it worked with Python. You didn't have to have to go through those extra miles in explaining, but you did. Really appreciate your time for doing all of this for us. As for me, you'll always get 2 thumbs up.
Thanks! I appreciate that, I'm glad you find the tutorials useful!
For everyone who is struggling with the chrome browser not being able to access files from your file explorer and don't want to install a server, here are the simple steps you need to follow:
1. Close all instances(tabs and windows) of the browser.
2. Open Task Manager and make sure no Chrome processes are running (Chrome extensions can still be running). If any processes are running then end them.
3. Open cmd prompt and navigate to the directory where chrome is installed. Example: cd "C:\Program Files (x86)\Google\Chrome\Application"
4. Start chrome from within the cmd prompt using --allow-file-access-from-files option. Example: start chrome.exe --allow-file-access-from-files
5. Now drag and drop the .html file to this window and you should be able to see the textured cube.
To avoid typing lines in cmd prompt all the time, I created a batch file.
FileName: open-chrome-withfileaccess.bat
Content:
cd "C:\Program Files (x86)\Google\Chrome\Application"
start chrome.exe --allow-file-access-from-files
exit
Now just execute the batch file to launch the browser with the said option.
10:46 It really is the little things that keep us going
Tip: You can hide an HTML element (like that image) just by adding the word "hidden" to the image tag. For example:
You don't need to set the width and height to zero :)
Heads up for anyone using a larger texture (or if it only works some of the time). Adding a small delay on the Init function lets the texture load before texImage2D gets it. Something like setTimeout(function() {Init();}, 100); gives it 100ms to load. 10ms is the minimum, which works for most small textures.
YES. So far so good, thanks a ton man.
Nice tutorial. I was able to follow and accomplish what I have been making excuses to put off : D.
Another quality tutorial fella! Quick note - if anyone is having issues with http-server caching, this may sort your problem 'http-server -c-1 -a localhost -p 8000'
which changes the port and turns of caching (I believe!)
My burning question is why do we bind and set the active texture in the main render loop if it isn't changing (at least in this example)? Surely we could move these in front of the loop and be okay, right?
For some reason, I didn’t get the security issue on Google Chrome on my Mac. Maybe the extra security from the Mac allowed me to bypass the security error.
pls make a video on GPGPU!
3 down! thanks for these!
23:20 doesn't work with Python3, but there's an easy fix.
python -m SimpleHTTPServer
returns an error saying
No module named SimpleHTTPServer
Instead, try
python3 -m http.server
or
python -m http.server
if you have Python3
Then search for localhost:8000 in your browser.
It also works with XAMPP pretty easy, nice tutorial
Hey thanks for doing this tutorial. Just wondering, is it possible to have a distinct image rendered on each face??
Glad you enjoyed it! Yes, there absolutely is. For a cube, you can split the input texture into some sort of grid, and put the image for each face in a separate cell - for example, the top face is in the top-left third of your texture, forward face in the top-middle, etc. Instead of using UV coordinates (0,1) on each side of the cube, you might use (0, 0.333) UV for the top, (0.333, 0.6667) U and (0, 0.3333) V for the front, etc.
You can do all sorts of clever things with elaborate character models and textures, the subject to look more into is "texture mapping." The hard part of doing that lies on the artist creating the texture and model. I'm not very good at modeling or texturing so I can't say much more than that, but it is an interesting study with a lot of great resources out there.
hi. First of all thanks your video. it is very helpful. But I have Problem. I use vue.js. I coded what you coded. İt works. but I refresh the page, image did not come. I went to another page and return my webgl cube page, image run. When I every refresh my website, image does not come at fisrt time. What is problem ?
Hmm... I don't know offhand what the problem is, I'd have to see the code - I'm not familiar with Vue.js, but that sounds to me like a DOM lifecycle thing? Or maybe a change detection issue. Maybe your WebGL code is running before the DOM has been placed? Or Vue is swapping out the canvas after your WebGL code runs, and then not re-running your WebGL code? I'm not sure - I'd guess it's a lifecycle thing, but don't know.
Hi! I did make this cube but the texture does only load on refresh.. How can I fix this? I think it's something with cache but not really sure...
Hmm, tricky... I've had an issue when using `python -m SimpleHTTPServer` with loading some files, I don't really know why but using the NPM http-server instead (www.npmjs.com/package/http-server) has fixed it for me. If it's a cache thing, you can disable the cache while developing by keeping the developer tools open (Firefox and Chrome, probably Edge/IE/Safari too but I haven't checked). F12 to open the dev tools, there's a setting (usually "Disable Cache") that you can enable, that'll keep the cache turned off.
If you go to the network tab in the developer tools (F12 usually) and load the page, does it look like the image loads? There'll be a list of files that are loaded with the webpage along with the status codes, types, etc. The image you load should come back with a 200 code. If it doesn't the first time, but does afterwards, then it's a problem with whatever server you're using. If it does come back with a 200 the first time but doesn't show anything, disabling the cache should fix it - though that only helps you (it doesn't help if you're trying to show other people).
Thanks for the video. It was very informative. I did, however, run into an error that I couldn't fix unless I switched browsers. Up until the point where you open the server everything was working fine on Chrome, but upon trying to run on the server I got the error :
Failed to execute 'texImage2D' on 'WebGLRenderingContext': No function was found that matched the signature provided.
at InitApp (app.js:229)
Switching over to Edge made it work fine, but I couldn't find any way to make it run on Chrome.
Hmm.... Interesting, that's a WebGL standard call, it should work well between all the browsers. Thanks for the heads up! It's possible I called it in a non-standard way somehow (though I tried to scrub all of my API calls to make sure they were correct) and that Chrome caught it while the other browsers ignored the errors or something.
I'm glad you enjoyed the video, sorry you ran into a problem while running the code!
@@peterhassaballah2024 Which is why he told you to run the live server. He spent about 5 minutes explaining this error in the video.
For some reason everything works fine in Chrome, But I cannot get the cube to render with the image in Edge, it remains a black spinning cube.
Hmm.... that sounds like a texture issue, check the console for warnings - browsers usually do an okay-ish job of putting WebGL errors there. Unfortunately it's really tricky to debug WebGL issues like that - Edge is usually pretty good in my experience, but there are weird things here and there.
You are a champion!
hey, first thanks for the tutorial is awesome!
secondd, why do u put the binding of the texture in the main loop?
greetings!
Thanks! Good question, it doesn't need to be there. You only need to swap out texture bindings when the texture itself changes - in this tutorial, it never does, so putting the binding inside the render loop is unnecessary.
It's been a long time since I wrote these, but I'd guess that I probably put it there to explicitly specify the texture near the code that also specifies other properties of the object in that frame (matWorld, matView, matProj).
When rendering many objects with different textures, you'll need to swap them out in the render loop before using the desired texture - in those cases I like to keep texture binding somewhat near binding other properties, unless I'm able to batch the calls to avoid repeated texture updates.
@@IndigoCode okay, again thank you so much!!
at approx 13:07, not every U, V number corresponds to the pattern of -1 = 0 and 1 = 1. As you go into the Left section, and Right and so on the pattern seems random to me. Can you explain why that is?
Yeah, it's a funky pattern. The XYZ part of the vertices represent the 3D position of the vertex. Each segment of four vertices forms one face of the box - labeled by the comments (Top, Left, Right, Front, Back, Bottom). Each side will have a full version of the image, which is a square that is formed by the UV coordinates , , and . For each side of the cube, I picked a vertex to be the lower left part of the image, one for the upper left, etc. For this symmetric image, it didn't really matter which I picked, so long as upper-left and lower-right were always diagonal, and same for upper-right and lower-left.
Hey can anyone tell me why are we binding texture again in the loop?
What if I want to use different textures with different sides of the cube? Do I have to draw one side, then call bindTexture activeTexture, then draw another side and so on?
That's one option. You can also use different texture coordinates for each side, pointing to different parts of the texture, and put pictures of the different sides together in the same image.
There's six sides of a cube, if you split an image 3x3 into smaller squares you can fit all six sides into it, and have three squares empty.
You can also use a cube map in some circumstances, though I think that's more commonly used for reflections and skyboxes (probably a performance reason).
Hey, I don't know if you are still active but by any chance could you tell me how to place a texture onto a rectangle in stead of a cube. The texture comes in the form of an ImageBitmap. Thanks in advance. :)
Very helpful my friend!
Thanks, I'm glad!
So if I want to draw a rectange and an image, do I need two different shaders? Does it make everything slower? Is it possible to merge the two shaders into one shader?
Great questions, and the answer to all of them is "it depends".
It takes time to switch shaders. Not a long time though, so it's usually worthwhile to have different shaders to do different effects if one effect is much slower than the other - you make up the time you lose switching shaders by saving time on drawing all those pixels at a lower cost.
If you wanted a rectangle that was a solid color and a cube, you could take a small image (1px) of the color you want to use for the rectangle, and still use the same shader for both. Or you could write two different shaders (one to use textures, the other solid colors). I don't think there would be a huge difference in speed, but I would guess using the same shader would be faster.
But say you wanted to make a scene with a lot of cartoon-y, flat shaded objects like this crate, but also some metalic, shiny rocks (Breath of the Wild does this a lot, it's a neat style). Reflections and shininess are much more expensive to calculate than flat colored objects - you could use the same shader for both by using a texture to represent the shininess of an object and just passing in a plain black texture for the cartoon-y objects, but you'd be much better off using two shaders to avoid having to do the extra (expensive) lighting calculations and texture sampling on most of the objects in your scene.
It is possible, but almost never necessary to merge multiple shading styles into one shader - have something like "if (isShader1) { ... do first shader logic ... } else if (isShader2) {...}". If your GPU batches any fragment executions for the more expensive branch with a large batch of cheap fragments, then all the cheap fragments still have to wait for the small group of expensive ones to finish. Plus, writing complex shaders is a huge pain to debug.
The only time I can think when you'd want to combine many shaders into one is if you're writing a shader to do raytracing without using a realtime raytracing API (DirectX 12, Vulkan) for a small area of the scene - metaballs is a great example of this. In that case, you'd have to have multiple shader functions all in the same shader file, because that hack to get raytracing works requires you to draw a single flat square covering the entire area where all of the raytraced objects might be drawn and do some clever math to actually perform the raytracing.
That all said, unless you're writing a ton of frivolous shaders, you probably won't notice a performance hit - especially if you're careful to only switch them when necessary (batch together your render calls to draw all things with shader1 before switching to shader2, etc).
@@IndigoCode Thanks for your reply! Never thought of using 1x1 images. But now I've settled and am using multiple shaders for different needs. Yeah, I think I'll batch render calls and draw stuff in order according to the shader it is using. I am making a little "engine" for drawing graphics for fun, currently it just has a viewport and all these functions you usually can access via the 2D context. Again, thanks a lot for that valuable piece of advice.
Hi. I got an error " Uncaught DOMException: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image " and Figure Hidden
That sounds like you're running your page by just opening up the file in a browser - so the URL bar will show something like "file:///..." There is a security policy in place that prevents you from running GLSL code or using images that comes from a different website, or "cross-origin." To fix this, you'll need to use a local webserver.
If you have PHP installed, put it under your "www" directory and use the URL "localhost"
If you have Python installed, use the command "python -m SimpeHTTPServer" while in the directory of your project, and go to "localhost:8080" You can put that command in a file called "server.bat" and run it if you don't want to mess with the command line yourself.
If you have NPM installed, there's a simple server you can install with "npm install -g http-server", after which you can run the command "http-server" and go to "localhost:3000". Same as with the python instructions, you can put thatcommand in a "server.bat" and run it by double-clicking if you don't want to mess with the command line.
To be honest, this whole requiring a server thing feels more like an attempt to inconvenience developers and push all web applications to be purely cloud-based, and potentially enforce always-on DRM... cross-origin also won't explicitly stop malicious code from executing, it just means the hackers will put the code/viruses somewhere in such a way it doesn't break cross-origin policy. Meanwhile, the days of the local web app and testing web apps locally is gone.
I also feel these 'easy' server packages are quite the contrary...
It should be solely up to the user to allow/deny applications to access local files, especially local applications. something that's actually HOSTED online is one thing. And as for protecting assets from your server from being grabbed, honestly, server owners should configure their own servers to allow/deny access to stuff. A majority do not, and that's their choice/problem.
The malicious code side, hard to say. But the problem doesn't exist solely in cross-site code execution/injection, but also in the fact there was an underlying security exploit, already. If cross-origin resource policy is to protect the client side, it fails gravely. Hackers will just upload their malicious code to their own site (or break into someone else's) and execute it that way. From the side of protecting the assets on your site from being used/lifted by another, you really should have the site set-up as such it's very hard to do in the first place. The number of implications it could have on a whole variety of web applications and entire sites is immense, especially if it were to be brought to its truest form, which is to block EVERYTHING that came from "cross-origin"...
Of course, there's currently a double-standard on what it impacts, so...
No offense to you if you DO believe in this, but I don't, and it would be very hard to convince me otherwise. Seems to me more like an excuse to avoid fixing (or testing for) the underlying security issues that allow XSS to even WORK, or for site owners/admins having to avoid learning how to PROPERLY protect their system and/or resources, all of this at the expense of the the users and developers that just want the content they're trying to view or create to even WORK.
Thanks for these tutorials, they are well-made and informative.
I'm also curious, how would the cross-origin problems affect something that was generated by code (thus has no origin besides the memory) , or was embedded into the scripts/HTML directly via text-based encoding systems like base64? And just for kicks, the file upload tag/system?
Also, I also cannot think of any examples, but iirc, it IS possible to put malicious code on the GPU, and the effects of the GPU seriously failing are often crippling/fatal to the impacted device. But, I don't see how cross-origin policy can possibly mitigate that. Just means if I were a hacker that knows how to put malware in the GPU, I'd put my bad on my own site, and draw my poor victims in with something like "Play MineCraft Online, for FREE, no account/registration needed!" then, BAM! Their computers crash/die. It IS possible to append other data to a file, like a PNG image, but really, the programs that are reading those should be designed to detect that. I did read about a Java exploit that used such an approach. Again, the plugin should've been checking there's not a .jar attached/embedded to another file, which was addressed eventually. JS and others have numerous exploits that don't rely on XSS and similar, though. I seriously HOPE webGL has the necessary levels of security and even error-checking to prevent doing something that kills the computer and/or GPU, regardless of what method is used to introduce it. Writing Assembly or C is dangerous for more or less the same reasons.
This is discussed at 20:00 in the video. :)
Very very helpful, Thank you!
Ah. The Witness. Great game
Hi! How hard would it be to add an image (imagine a small sticker) on one of the faces? A lot would have to be midified or can only be added?
Are you asking about adding an image on top of the texture (like adding a sticker onto the crate texture)? You can do this by editing the texture image using an image editor like GIMP, Paint, or Photoshop.
Hi. I got an error "WebGL: INVALID_VALUE: texImage2D: no image data" even when I copy/pasted your code. Still, your online demo works fine. I am using python SimpleHTTPServer. What could the problem be?
Hi! So, it's impossible for me to know for certain what the problem is (since I can't see your code and the error), but I think I know what the problem is.
The most likely issue is that your code is failing to pick up the Image object - try running document.getElementById('crate-image') in the console. It should give result of an tag. If you get 'null' instead, check your HTML code and make sure you have this line of code in there: . If you copied and pasted the code, there shouldn't be any typos in 'crate-image' in either the JavaScript or HTML code, but that's another place I'd look.
If you do get the tag in the console, it's possible that the script is executing before the image is loading. To fix that, just make sure that the tags for loading app.js come in the body after the tag loading the image. This will prevent app.js from executing until the image is done loading.
While much less likely, there are some other things that cause an INVALID_VALUE error to be raised: If width or height is negative, if the image is bigger than the maximum texture size your GPU can support (which it isn't, if you can run the online demo), or some things involving cube mapping (which we're not doing here).
There's a whole list of what that particular error can mean here: msdn.microsoft.com/en-us/library/dn302435(v=vs.85).aspx
Fantastic! The problem was that the image tag was placed after the script. Thank you very much.
Webpage got blocked by our Company: "SPAM". Can't see the live demo. Doh
I want to use the webgl cube for one global project can I use the code.
Totally! It's all open source, feel free to use any of it.
Why not? Nobody will know
If you have PHP installed, you can also use php -S localhost:
Anyway, thank you for your lessons.
+Zolat Eater Sweet, good to know. I'm glad you enjoyed them!
I got an error "INVALID_VALUE: texImage2D: width or height out of range" when i copied the source code. The error is in this code:
gl.texImage2D(
gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,
gl.UNSIGNED_BYTE,
document.getElementById('crate-image')
);
In case anyone else is looking for the wooden create, opengameart.org/content/wooden-crate
Hello. I added image. But object does not seem. How can i solve this problem?
(1) Check to see if the image is being loaded by the page at all - in the developer tools for all browsers that I know of, there's a `network` tab. You can look in there to see if the image gets loaded, or if there's a 404. If it's not loaded, check the path you use to reference the image, and make sure the image is in the right place in the folder you're serving.
(2) If all that is good, make sure there's no WebGL warnings in the console. It's possible you missed a parameter on loading the image.
(3) Check your buffers to make sure you're sending over UV data, and make sure you're setting the vertex attributes correctly. If you followed the code, you should have that.
Check the image format . I had some issues using .bmp images :(
Hmm... That's odd. WebGL should be able to handle any HTMLImageElement that can be processed by the browser - check the JavaScript console for warnings/errors, there's a bunch of things around textures that can go wrong (image format, non power of two textures, cross-domain request)
Firefox is usually better at reporting WebGL warnings, though anything that causes problems to happen should be reported by Chrome too.
It hurts to see each video of the series has less views over time.
Yeah... For awhile, the first several videos had almost exactly half as many as the one before. I figure they're pretty long videos, and it's easier to figure things out once you've learned the fundamentals (less need for later videos).
Still a lot more views on all of them than I ever expected when I made them though :-)
My guess is that people click on the first video thinking it's easy, then when they realise the reality, they slowly drop out one by one. A bit sad really. I don't understand 50% of what I'm writing in these tutorials, but when finished I hope to do my own research and figure out what does what and how to do more complicated and fun things with it.
@@Rocco-tb9ih I can see how it seems sad, but the way I see it, I think it's good that video tutorials like this one help viewers get an idea of whether or not WebGL coding is right for them. They may have stopped watching after the first video, not because they "gave up", but because the first video gave them enough info to decide they would rather not pursue WebGL.
15:42 - A cross-platform PC game developer that also plays PC games? Hope is restored! Take notes, Blizzard.
2:08 f*cking-alpha-texturing... I laugthed so hard x'D
Haha yeah... I didn't do a blending/transparency video, I did start to put stuff together for it and it did _not_ go well :-P
LOL
GOOOOOOOOOOOOOOOOD VIDEO
got stuck in the security error in console,and in my pc it is showing me a DOMException !!! :(
can anyone help me
Is there any way to get rid of that ugly pixelating/aliasing on the edges?
anti-aliasing is uglier
@@911WasActuallyBears That depends on what method of antialiasing one uses. You're right that anti-aliasing _alone_ doesn't solve the problem, and that it can even make it worse. Anti-aliasing with sub-pixel multisampling, on the other hand… ;J
IndigoCS Channel: github.com/sessamekesh/IndigoCS-webgl-tutorials
The whole security nonsense totally turned me off of this. Thanks, but I'll stick to C + OpenGL.
lol.
i see you everywhere!!
ah back too simple c/c++ huh??
i honestly have yet to see what is so much easier about these "modern" and "cool" and "easy" languages. quiet honestly they are much worst.
Bro, you have no idea what you're talking about... Just upload the project to ANY server and it works.
racist