i guess im asking randomly but does any of you know a tool to log back into an Instagram account? I was stupid lost my account password. I would appreciate any help you can give me!
Heads up for anyone getting memory access errors when reading in the file. Since the default shader type is NONE, if you have any trailing empty lines (like I did by accident) in your Basic.shader file VS will throw a nasty error. Either remove the empty lines at the beginning of the file or add an if statement to check and make sure you are reading a shadertype that isn't NONE
This happened to me as well, thank you for the heads up. To any noobs like me, the reason it fails when there are empty lines in the shader is because we use the type as an index to access the ss array. Since NONE = -1, we are trying to access ss[-1] if there are empty lines before finding "#shader". It took me a minute to realize this. xP I fixed it by adding if(line.length() == 0){ continue; }
use seperated files to save the shader's source code has a advantage that when the code cannot compile success, the log gives error message with the line number, and text editor can show line numbers, so you can quickly locate the line int text editor to find out what is wrong in the source code.
For those who are willing to use 2 files : static std::string parseFile(const std::string filePath) { std::ifstream file(filePath); std::string str; std::string content; while (std::getline(file, str)) { content.append(str + " "); } return content; } here you go
@@redpepper74 not a big deal in this case but, in stringstreams you can insert int, float, char, double or simply anything you can do with a cout and cin, why we don't always just use stringstreams instead of just strings? because they are larger and take more place in memory (if I'm not mistaken), I'm quite a beginner so you probably would want to make sure from some advanced programmer
@@m96fa40 Coming back to it again I bet it’s faster to use a stream because with a string there’s extra overhead for concatenation but streams are built so that it’s fast to append. At least that’s how it work in Java with String vs StringBuilder
In the long run in a bigger code you will notice how stupidly slow is to open two or more files a lot of times :) Thats the reason he is doing that as well
Thing is, you gotta kinda write something like this anyways, as GL doesn't have a built in function to ingest glsl from a file. This is just beefing out the file reader a little bit to give a BIG convenience boost
@@KyleHarrisonRedacted If boost speed is the point, e.g. a scenario where you have to open and read files multiple times, you could open files once and keep them in memory (heap for example) as theses files are static. I see no reason to complicate so much the code just to read a single file. And the parsing of the single file in the way Cherno wrote has its perfomance impact itself. Despite this little critique, this series on opengl is really great! I am loving. I thing that each developer should thing and decide how they should organize their source code.
The moment when Cherno says he doesn't like to be proffesional but at the same time he makes one of the best, most proffesional-looking programming tutorials heh
@@puppergump4117 If you are knowledgeable enough about c++ then you can do it your own way. The same applies to the OpenGL API. He always explains what he is doing. So being able to implement it in your own way won't be hard. However, if you are a beginner in either c++ or OpenGL then, of course, you won't be able to write equivalent code. And you shouldn't complain about copying because you're just learning.
@@nilanjanmukhopadhyay8369 Just learning is fine, but if you're trying to code along with him and he's like "So I did some event handling off camera" that's kind of irritating.
@@123akash121 Don't worry, I've found that "following along" is bad anyways. If you wanna make a game engine you need to get used to making many other projects on your own first. Otherwise you're stuck with the burden of making the engine fit with what you're trying to use instead of the other way around.
I was trying so hard why it wasn't parsing the files. I tried outputting some things and I found out that no input was happening. I eventually found out that Visual Studio's "filters" aren't actually folders and they are just a way of organizing things; to call upon whatever file you are looking for within a filter is the same as if there wasn't one at all: if you just store the file in filters then it's location is at "Basic.shader" and not "res/shaders/Basic.shader" because it doesn't create any folders.
@@Rocco-tb9ih It's quite alright. Everything had turned out fine and working. I don't really want to continue this argument any longer. Thank you anyways.
Having separate files is (beside the clear advantage of being able to combine different shaders together) just simple management of data. With the logic you follow in the is video one might ask "Why split stuff into header and source file? Why have multiple of each?".
File reading speed.... in the long run when things get more advanced and much larger it would be more efficient to load the shaders from one file since C++'s file loading is slow. Though every one is entitled to their own opinion.
@@lilcatfriend4575 Yep precisely, every time you need to open a shader you're going to run a system interrupt which can be very expensive. If pairing them off makes sense (for specific vertex/fragment combos) then it will half the amount of times that expensive call is made.
@@NWProductionsHD Still, in that case, it shouldn't be the shader loading code's business to do that, but of a separate resource loading module that makes it transparent to all its clients, like a "virtual file system" or "archive". The resource loader opens this single file with a blob of data and parses it to the point where the next resource begins, and then passes it to the appropriate resource object to load its data from there. Once the resource object is done, the resource loader takes back and passes it to the next appropriate resource object to load its data from there, etc.
@@lilcatfriend4575 I have quite a bit of trouble with the whole "C++ file loading being slow" thing. It's purely an operating system and implementation bottleneck, not a language issue. There are things I hate about the C++ stream system, but speed is not the language's fault.
Can't you just preload them in batches? I mean, how many and how complex different shader files do you realistically need to have for that to start to be a problem?
Thanks for sharing your knowledge. I'm venturing into using openGL with Java and I'm having success following your tutorial even though it's in C++. The challenge is more to deal with when you use pointer manipulation, but gathering what I know about the Java language, I've managed to proceed. Thank you !!!
Your logic behind placing the shaders into one file seems flawed. Why dump them all into one file, only to have to manually parse it into separate strings later on? Even more ironic was that you complained that C++'s method of reading from files is slow, even though you did string comparisons line-by-line to do the same thing as writing separate files.
Probably not for use in production mode, but to learn stuff it's quicker to write all the shaders into one file rather than multiple. With some caching it's easy to avoid the overhead
@@thelonearchitect I don't think so. More complexity like your own file-format(what 2 shaders in one file actually is) or introducing a caching solution, where a dozen things may go wrong only distract from the learning goal.
@@kaloyanmanev GTA V only loads once per session.. People still complain about that. Speed of reading and writing files is important, no matter when it is done.
For people who want a simple solution to read separate shaders(each one has its own file):#include #include static std::string parseShader(const std::string filePath) { std::string code; std::string line; std::ifstream file(filePath); while (getline(file, line)) { code += line; code += " "; } file.close(); return code; }
There are one issue in the code. we should use _malloca instead of using alloca, some failures like stack overflow will cause problem if we use alloca.
For anyone running OpenGL 2.1 and GLSL 1.2, I found that the shaders would compile after I removed the `;` after `void main() {}`. #shader vertex #version 120 attribute vec3 position; void main() { gl_Position.xyz = position; gl_Position.w = 1.0; } #shader fragment #version 120 void main() { gl_FragColor = vec4(1.0,0.0,0.0,1.0); }
for anyone who gets white screen: go to the project delete the class and void u made and stick this in because you probably did something wrong and cannot do it and also the "else" statement gives an error which i am not so sure about class ShaderProgramSource { public: std::string vertexSource; std::string fragmentSource; }; static ShaderProgramSource ParseShader(const std::string& filepath) { std::ifstream stream(filepath); std::string text; std::stringstream ss[2]; enum class ShaderType { NONE = -1, VERTEX = 0, FRAGMENT = 1 }; ShaderType type = ShaderType::NONE; while (getline(stream, text)) { if (text.find("#shader") != std::string::npos) { if (text.find("vertex") != std::string::npos) { type = ShaderType::VERTEX; } else if (text.find("fragment") != std::string::npos) { type = ShaderType::FRAGMENT; } } else { if (type == ShaderType::VERTEX) { ss[0]
YO if you want to have multiple files like me, just seperate them and do this: static std::string ParseShader(const std::string& file) { std::ifstream stream(file); std::string line; std::string shader = ""; while (getline(stream, line)) { shader = shader + line; shader = shader + " "; } return shader; } instead of returning a struct, return a string and then in the main do this: std::string VertexSource = ParseShader("vertex.shader"); std::string FragmentSource = ParseShader("fragment.shader"); This is in my opinion cleaner way of doing things. DOnt forget the " ";, else it wont work.
@@bulentgercek I try to help out when I can. I really didn't see a reason to keep both shaders in the same file and then have all of this extra code especially for what was explained in the tutorial. Obviously Cherno is light-years ahead of me in opengl and c++. When I wrote this comment I was still in junior year of highschool and had very little understanding in both c++ and opengl. Now I guess I am better at c++ but my opengl hasn't improved all that much :/ so I'd take what I wrote here with a grain of salt. It will work but I can't tell you if it's the better approach.
In fact, looking back at this, it is definitely more performance demanding because it's calling parseShader twice. There is a workaround to that, just change the parameters to take in 2 strings and then do parallel read of both files.
OpenGL is perhaps the most fun I am having learning something new in programming. Because I am also relearning C++ in the process. I will say, Rust is still my go-to language.
8:30 Oh joy! The Cherno endorses FILE! I like to use C as much as possible but when I have to use C++ I feel somewhat obliged to do things 'the C++ way'. Of course that's nonsense, thanks for the reminder. I wasted a bunch of time to write a preprocessor program that converts a shader file into a char*, so now I feel obligated to use that for my shaders. I suppose it depends on whether you want to be able to change your shaders without recompiling... that's probably a good idea...
Thank's a lot for all your videos. Not easy to adapt with in visual studio code with mingw but it works ! I'm learnig a lot ! I added a little test in ParseShader : if(type != ShaderType::NONE) ss[(int) type]
hey can you tell me how you setup opengl in vscode ? I tried it myself a million times before downloading the bloated msvc to just get started with SOMETHING.
Well, I needed to add src before the path- so it was src/res... Try to print the file out so You can find it easily { std::ifstream f("file.txt"); if (f.is_open()) std::cout
You've got an issue in the ParseShader (well not a problem here, but it can give errors in the future). If the first line of your shader doesn't contain #shader vertex of #shader fragment, it will try to access ss[-1]. Of course you can say the first line HAS to contain that, but even a comment (like copyright) could give you an error
He actually adressed this on his Discord. The point of this video was just to show how you can combine shaders in one file, so he didn't really concern himself with that. So go ahead and add a fix for your code.
Took me a while to figure out that the getline was reading the entire file as one line, because the shader file end-of-line was set to CR. After I set it to CRLF it took it in line by line and it worker fine 👍
Yep it is simple and clean but there's still no syntax highlighting, error checks or code completion. For real shaders everyone should use files and error tagging.
If you're having trouble like me, the getline function is getting the whole file instead of one line, just add the delimiter on it. It'll be like: "while(getline(stream, line, ' '))"
Hey so I'm pretty new to all this stuff, but I was wondering why (aside from comfort), do you combine the shaders into a single file. I like the idea of keeping things in separate files, and there seems to be a convention for GLSL file extensions (.frag, .vert, etc.). I know file reading is pretty slow, so it can be advantageous to minimize the amount of files that need to be read, but is that not avoidable with some sort of cache system? Am I missing something?
in one video you have taught me so much on professional c++ programing than my entire life looking at stack overflow. so, does how you properly use struct, enums, sstreams, string, ftream nah I cant enumerate them all !thanks so much!!
OH MY GOD YOU ARE A SAVIOR I was looking over my code because it would compile just fine but the triangle wouldn’t show up I tried this comment thinking it probably wouldn’t work but was worth a shot and it did thank you so much
getline isn't defined despite having string included. Edit: never mind, it just took visual studio a very, very long time to figure out that i had included string (about 10 minutes).
i'm not really good with OpenGL, but how all this time when learning i did it is basically made my own system that just splits one file into 2 parts whenever i type in the lines "@vertex" and "@frag", so basically it works the same way as reading the 2 files except i write everything in a single one, not sure if that's a good way but i'm about to find out :D Update: i just watched the video and the only thing i used was the way to return 2 shaders at once, since i just had 2 different functions one to return the vertex one and another for the fragment
I ended up having to use this for my relative path being OpenGLChernoProject es\shaders\Basic.shader ShaderProgramSource source = parseShader("../res/shaders/Basic.shader");
It would be nice to be able to have separate files for shaders like in the video, but also to be able to have the shaders in the compile executable when the program is built...
15:30 actually shouldn't he use a backslashes \ instead of a forward-slashes / in the filepath when he is working on windows? (and not forget to escape the backslash in the string as "res\\shaders\\Basic.shader") And how do I make this protable so it uses / on unix and \ on windows?
For people using newer versions of Open GL, make two files ( one for vertex shader, one for fragment shader).Then read from them and convert them into strings the same way he does. Two main functions don't compile for some reason.
The triangle is still white and nothing gets written from the Basic.shader in my console. All the code is exactly the same with the same paths. I don't know what else to do
Does anyone have any recommendations for the following warnings: C6385 and C6255 (this is for alloca, I just found on microsoft docs that it would be better to use malloca, which doesn't work for some reason)? For the C6385, I had to add an if statement: if ((unsigned int)type
yeah i ran the program once got a red triangle then the it started not working randomly. and i got these errors. I just did what microsoft said and used _malloca then did what you said and now it all works again thank you for that if statement I don't understand it but it works.
You need to keep track of line offsets for the different shaders, so in case of a an error with a error line number, you can print out the real line in the .shader file...
Somehow my While loop quits after the first line. Any ideas? Code is 100% identical to his.. EDIT: Fixed it. Somehow the getline function stored the whole file as 1 line. You can add a delim attribute to it that splits them into lines, like (getline(stream, line, ' ')). Thank Cherno for learning me how to debug. :}
Man I was struggling to figure out why the getline wasn't working like the while loop wasn't even running, turns out I was specifying the file extension incorrectly, in the file path I was typing in Basic.shaders, instead of Basic.shader
No matter what I do to the file path it always seems to yield a null file stream, noticed comments about filters in Visual studio but I cant seem to get the file to ever be read by getline command in the while loop
Just a quick question. I followed your previous tutorial and managed to get a red triangle showing. After deciding to play with the code, I accidentally deleted the glDeleteShader() functions in CreateShaders, and the triangle became white again. How come? Is this something that is just how OpenGL works, and if it doesn't get a 'delete' command, aborts?
Your point about not having 2 seperate files for each shader does not makes to me. What if both your shaders are complex and big? Surely then it become annoying to navigate that one file it becomes too big?
I didn't want to create a struct just for the return so I just made it like this: static void ParseShader(const std::string& filepath, std::string* pVertex, std::string* pFragment) { [...] *pVertex = ss[0].str(); *pFragment = ss[1].str(); } and called the function like this: std::string vertexShader, fragmentShader; ParseShader("res/shaders/basic.shader", &vertexShader, &fragmentShader); I could use a bool as return which indicates if everything went fine but im lazy today
@ICH WEISS....: (Ab)using parameters for return values is bad practice. With that approach, you could as well set them into some globals :P @@sapuseven6119 Well, at least he didn't put it all into one word, as Germans tend to do :q
Hello, got an issue, when a compile, what returns to me it is a triangle with a basic shader, and on the prompt screen, gives me the error message, that could not compiler the shader, i dont´t know why but seems, that him cant find the path of file. In this case, what i need to do to fix this?
My granny had that exact same couch. It was covered in plastic and she wouldn't let anybody sit on it. She smelled like dried prunes. Good riddance granny.
Yes, my mother used it that way. She probably grew up in a family environment that should have been frugal. I'm sure she was removing the plastic on the couch when a visitor came. :) Frugal people. Respect.
I'm gonna bake the Basic.shader file as a resource into my EXE file since I set the configuration to put the exe file in a completely different directory, and even though while debugging the working directory is set to the ProjectDir for some reason the file isn't found by the ifstream object.
I know this is 4 years late but if anyone doing this now still gets a white triangle and it's because it's not reading your shader file, just delete the folders in the filepath and VS2019 will find it. So my filepath is literally "Base.shader" and it's working.
hey guys, I had the same problem as you. Its happening because the ShaderType is defaulting to None, meaning its trying to read from ss[-1] which doesn't exist. My solution was to replace the "else" statement in the while loop with: else if (type == ShaderType::VERTEX || type == ShaderType::FRAGMENT) { ss[(int)type]
On recent GL/GLSL versions you can no longer combine multiple shaders into a single file, because if you try to compile a shader with _#shader__ [type]_ in the top of the file it will fail to compile
Got it to work. I put the file path onto separate lines putting the name and then the slash on separate lines and it worked so i went back to on one line and it worked???
Joseph walker Oh i probably know the reason. There is a thing called escape sequence as you saw from the warning. You probably know about ' ', it is the new line character and it is one of the few escape sequences. In your code you probably wrote \s somewhere and compiler tought that it was a escape sequence. There are two ways to work around this: 1) Replace \ with \\. \\ is also an escape sequence (ironically) and it means \. 2) Use / instead of \. In this video Cherno used / too. You probably used the "wrong" slash when you first write the code. Then when you were putting the string into seperate lines you fixed the problem unintentionally. Edit: Edited the format for readibility.
Hi. If anyone has mood to answer this question, when I have several shaders, each has some attributes with same layout location, how can I tell OpenGL that this attribute belongs to that shader, or should I use the different layout locations for each of the attributes?
Or just use a pointer to one of those strings and reset the pointer in the conditional to point to the other string, then use `(*currentString) +=` for appending to whatever string it currently points to :q No need for string streams.
IF you want to put both shader sources in one file it might be a good idea to name file .txt if you are having trouble with shader syntax highlighting extension errors.
Having a strange error on my end. When I run the application i get an error that one of my shaders failed to compile. The strange thing is that the triangle appears with the correct color even with the error. The error i get is "C7458: 'layout(location)' requires '#extension GL_ARB_separate_shader_objects : enable" When i add this extension the shader compiles, but the triangle does not appear at all. Does this have to do with having 2 shaders in 1 file with recent versions of OpenGL?
I had the same problem. My problem was that in the vertex shader the direction of the position vector was wrong. It should be "in", not "out": layout(location = 0) in vec4 position;
I'm having trouble printing out the source code in Basic.Shader. My code is working up to the point where "while (getline(stream, line))" is called. the file path has made it's way into the ParseShader method, just for some reason the lines are not being read. So the problem has to lie between the ifstream and getline(stream, line). I'm running the latest OSX and Xcode, which is usually why I run into issues TheCherno does not have. Any help is greatly appreciated.
I hope you already solved this one, but for any future visitors who have this particular issue: it could be an encoding thing. Different OSes use different line endings, which is known to cause problems with getline(). For instance, Windows uses both carriage return *and* newline (" "), while Linux just uses newline (" "). If you're running on a machine that only permits getline() to return on a Windows-style ending (" ") and you feed it a file that only contains Linux-style endings (" "), it will not terminate until it hits EOF. In other words, the **entire file will be read as the first line, with no obvious errors**. To be extra safe, just add an extra empty line between each line of shader code in your favorite text editor. OpenGL will ignore the empty lines, but you can be fairly sure that getline() will not.
I know I'm 5 years late, but I was using "add filter" which was not the same as creating a new folder. You can either delete the bit before your file's name, or add the folders manually!
It's done, for the persons that have the same issue you need to open the properties of your shader file and in the item type put the property of "Does not participate in build" and the make sure that you open your file correctly
I think there might be a better way to do this. What you need is to load the whole file as a string, then run it through a C pre-processor with some macros already defined that can filter out unwanted lines. There are some good C-preprocessors static libs out there.
Modern IDE's support .glsl format and can give quite a lot of useful information and highlight errors. Putting both shaders into 1 file makes it impossible. However for a small project this is totally fine.
I've spent straight a whole day looking trough my source code wth was wrong... I wrote ShaderType type = ShaderType::FRAGMENT; instead of type = ShaderType::FRAGMENT; so I've been re-defining the instance of the class all this time xD
Eli Howitt, thanks! You were spot on, I had to remove the semicolons after the main function. That was messing me up too! I'm on a Mac High Sierra, I also added glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); in order to use the 4.1 version of OpenGL.
you forgot to close the file, and using separate files is way better: - It maintains the consistency of one program is in one file. - Someone else looking at your code might get confused. - If you want to dynamically change the one of the shaders you'll have to load the file for one half of it?! - Its reduces the code by allot - No game engine that i know of will allow you to make a shader file and have two shaders in it. Doesn't make sense, please stop this madness
"Its reduces the code by allot" no, it just splits it into 2 files. But I strongly agree with "If you want to dynamically change the one of the shaders you'll have to load the file for one half of it" and "No game engine that i know of will allow you to make a shader file and have two shaders in it".
Yep and from what i have seen he actually uses two different files for each shader in his github projects. It doesn't really matter and at this point its really easy to change the code to get shaders from different files
I'm just a novice programmer but to me, reading in codes from a file at runtime that are actually executed without thoroughly checking the contents seems flawed to me. Huge security issue. Those shader codes don't change during runtime, right? Why not import during compile time with some compiler directives? Seems way more safe to me. Buy I might be missing something huge of course.
well, imagine having a big project with compilation times more then 5 - 10 mins. imagine you wanna tweak something in one of your shaders. most of your working day will be spent waiting for compilation :D
Was testing it the way you did incorrect in some cases? In my case nothing prints... I have already rewatched once... Anyway maybe I did something wrong
I thought I'd followed this exactly, but when I guess my shader file is being parsed incorrectly, as it doesn't work and the cout prints #version 330 core1214212142layout(location = 0) in vec4 position;1214212142void main()12142{12142 gl_Position = position;12142}1214212142 My gut says that I've used an incorrect data type somewhere and it's filling the VertexSource string with junk... but I actually have no idea.
I tried putting up the same code as cherno did but i could not work out how to seperate one file into two seperate strings based on what cherno wrote,.. so after a lot of tryings, i managed to create two seperate files for vertex and fragment shaders .. and worked it out as i know best .. hope its not a problem tho
Threatened to be injured by cactus---> moves to another location of the room. Cactus supremacy.
You could had just moved the cactus lad. :)
But this requires touching the cactus :q
Cactus lives matter
He could have harvested the cactus to make cactus green and pipe waterproofing
@@generichuman_ Minecraft moment
i guess im asking randomly but does any of you know a tool to log back into an Instagram account?
I was stupid lost my account password. I would appreciate any help you can give me!
In OpenGL series, we heard "I will make a C ++ video" a million times.
Heads up for anyone getting memory access errors when reading in the file. Since the default shader type is NONE, if you have any trailing empty lines (like I did by accident) in your Basic.shader file VS will throw a nasty error. Either remove the empty lines at the beginning of the file or add an if statement to check and make sure you are reading a shadertype that isn't NONE
Just happened to me. Thanks for the heads up!!
Thanks, also for any morons like me, do not forget to actually assign the shader type to variable "type" XD
This happened to me as well, thank you for the heads up.
To any noobs like me, the reason it fails when there are empty lines in the shader is because we use the type as an index to access the ss array. Since NONE = -1, we are trying to access ss[-1] if there are empty lines before finding "#shader". It took me a minute to realize this. xP
I fixed it by adding
if(line.length() == 0){
continue;
}
@@WeirdBrainGoo Thank you very much , just had a error saying "Exception thrown at..." and searched on the internet and did not find anything
yoo thanks man! got that problem and no errors were showing up but it didnt work so i deleted the empty lines and now perfect!
use seperated files to save the shader's source code has a advantage that when the code cannot compile success, the log gives error message with the line number, and text editor can show line numbers, so you can quickly locate the line int text editor to find out what is wrong in the source code.
For those who are willing to use 2 files :
static std::string parseFile(const std::string filePath) {
std::ifstream file(filePath);
std::string str;
std::string content;
while (std::getline(file, str)) {
content.append(str + "
");
}
return content;
}
here you go
std::ifstream file(source);
std::stringstream buffer;
buffer
i love you...
whats the difference between piping into a stringstream and appending to a string?
@@redpepper74 not a big deal in this case but, in stringstreams you can insert int, float, char, double or simply anything you can do with a cout and cin, why we don't always just use stringstreams instead of just strings? because they are larger and take more place in memory (if I'm not mistaken), I'm quite a beginner so you probably would want to make sure from some advanced programmer
@@m96fa40 Coming back to it again I bet it’s faster to use a stream because with a string there’s extra overhead for concatenation but streams are built so that it’s fast to append. At least that’s how it work in Java with String vs StringBuilder
You need a glass of wine and a cat to go with that new set.
That would be awesome.^^
How about a baguette too?
More like mountain dew and dorritos...
@@acatisfinetoo3018 complete with air horns and "OOOOOOHHHH" sound effects?
churn be like:"lets make a meta line detectioning system to split off our code into two lists instead of writing it into two files because COMFORT"
In the long run in a bigger code you will notice how stupidly slow is to open two or more files a lot of times :) Thats the reason he is doing that as well
Thing is, you gotta kinda write something like this anyways, as GL doesn't have a built in function to ingest glsl from a file. This is just beefing out the file reader a little bit to give a BIG convenience boost
@@KyleHarrisonRedacted If boost speed is the point, e.g. a scenario where you have to open and read files multiple times, you could open files once and keep them in memory (heap for example) as theses files are static. I see no reason to complicate so much the code just to read a single file. And the parsing of the single file in the way Cherno wrote has its perfomance impact itself.
Despite this little critique, this series on opengl is really great! I am loving. I thing that each developer should thing and decide how they should organize their source code.
@@victordfb just 3 if statements dude its cool
The moment when Cherno says he doesn't like to be proffesional but at the same time he makes one of the best, most proffesional-looking programming tutorials
heh
I don't know, he usually just shows the way that he does things and that makes it hard to learn without just copying him.
@@puppergump4117 If you are knowledgeable enough about c++ then you can do it your own way. The same applies to the OpenGL API. He always explains what he is doing. So being able to implement it in your own way won't be hard. However, if you are a beginner in either c++ or OpenGL then, of course, you won't be able to write equivalent code. And you shouldn't complain about copying because you're just learning.
@@nilanjanmukhopadhyay8369 Just learning is fine, but if you're trying to code along with him and he's like "So I did some event handling off camera" that's kind of irritating.
@@puppergump4117 he literally DID add some text on the last video on what was the mistake in the code in post/editing
@@123akash121 Don't worry, I've found that "following along" is bad anyways. If you wanna make a game engine you need to get used to making many other projects on your own first.
Otherwise you're stuck with the burden of making the engine fit with what you're trying to use instead of the other way around.
Your videos are pure gold :) Thanks for making this video series!
I was trying so hard why it wasn't parsing the files. I tried outputting some things and I found out that no input was happening. I eventually found out that Visual Studio's "filters" aren't actually folders and they are just a way of organizing things; to call upon whatever file you are looking for within a filter is the same as if there wasn't one at all: if you just store the file in filters then it's location is at "Basic.shader" and not "res/shaders/Basic.shader" because it doesn't create any folders.
He did say there is no concept of files in his c++ series
@@catorials444 Oh. Thanks. I guess I didn't understand what he meant initially.
@@JoseGonzalez-rt5fk He showed how to make Visual Studio only show files that are actually there..
You wouldn't have this problem if you did that.
@@Rocco-tb9ih It's quite alright. Everything had turned out fine and working. I don't really want to continue this argument any longer.
Thank you anyways.
@@JoseGonzalez-rt5fk Lol I didn't realise this was an argument, was just trying to help.
That's fine, good luck with everything!
Having separate files is (beside the clear advantage of being able to combine different shaders together) just simple management of data. With the logic you follow in the is video one might ask "Why split stuff into header and source file? Why have multiple of each?".
File reading speed.... in the long run when things get more advanced and much larger it would be more efficient to load the shaders from one file since C++'s file loading is slow. Though every one is entitled to their own opinion.
@@lilcatfriend4575 Yep precisely, every time you need to open a shader you're going to run a system interrupt which can be very expensive. If pairing them off makes sense (for specific vertex/fragment combos) then it will half the amount of times that expensive call is made.
@@NWProductionsHD Still, in that case, it shouldn't be the shader loading code's business to do that, but of a separate resource loading module that makes it transparent to all its clients, like a "virtual file system" or "archive". The resource loader opens this single file with a blob of data and parses it to the point where the next resource begins, and then passes it to the appropriate resource object to load its data from there. Once the resource object is done, the resource loader takes back and passes it to the next appropriate resource object to load its data from there, etc.
@@lilcatfriend4575 I have quite a bit of trouble with the whole "C++ file loading being slow" thing. It's purely an operating system and implementation bottleneck, not a language issue. There are things I hate about the C++ stream system, but speed is not the language's fault.
Can't you just preload them in batches? I mean, how many and how complex different shader files do you realistically need to have for that to start to be a problem?
Thanks for sharing your knowledge. I'm venturing into using openGL with Java and I'm having success following your tutorial even though it's in C++. The challenge is more to deal with when you use pointer manipulation, but gathering what I know about the Java language, I've managed to proceed. Thank you !!!
Your logic behind placing the shaders into one file seems flawed. Why dump them all into one file, only to have to manually parse it into separate strings later on? Even more ironic was that you complained that C++'s method of reading from files is slow, even though you did string comparisons line-by-line to do the same thing as writing separate files.
Probably not for use in production mode, but to learn stuff it's quicker to write all the shaders into one file rather than multiple.
With some caching it's easy to avoid the overhead
@@thelonearchitect I don't think so. More complexity like your own file-format(what 2 shaders in one file actually is) or introducing a caching solution, where a dozen things may go wrong only distract from the learning goal.
Also,, what's the point complaining about speed when this is done only once when the program starts...
@@kaloyanmanev it's kinda important as well.
@@kaloyanmanev GTA V only loads once per session..
People still complain about that.
Speed of reading and writing files is important, no matter when it is done.
For people who want a simple solution to read separate shaders(each one has its own file):#include
#include static std::string parseShader(const std::string filePath) {
std::string code;
std::string line;
std::ifstream file(filePath);
while (getline(file, line)) {
code += line;
code += "
";
}
file.close();
return code;
}
@@yanisfourel yepp. The "line abstraction" only exists in our head. No need for it when compiling shaders.
There are one issue in the code. we should use _malloca instead of using alloca, some failures like stack overflow will cause problem if we use alloca.
For anyone running OpenGL 2.1 and GLSL 1.2, I found that the shaders would compile after I removed the `;` after `void main() {}`.
#shader vertex
#version 120
attribute vec3 position;
void main()
{
gl_Position.xyz = position;
gl_Position.w = 1.0;
}
#shader fragment
#version 120
void main()
{
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
Looks like that semicolon was left over after the quotes were removed.
This comment saved my life. Spent so long trying to figure out why it didn't compile
for anyone who gets white screen:
go to the project delete the class and void u made
and
stick this in because you probably did something wrong and cannot do it and also the "else" statement gives an error which i am not so sure about
class ShaderProgramSource
{
public:
std::string vertexSource;
std::string fragmentSource;
};
static ShaderProgramSource ParseShader(const std::string& filepath)
{
std::ifstream stream(filepath);
std::string text;
std::stringstream ss[2];
enum class ShaderType
{
NONE = -1, VERTEX = 0, FRAGMENT = 1
};
ShaderType type = ShaderType::NONE;
while (getline(stream, text))
{
if (text.find("#shader") != std::string::npos)
{
if (text.find("vertex") != std::string::npos)
{
type = ShaderType::VERTEX;
}
else if (text.find("fragment") != std::string::npos)
{
type = ShaderType::FRAGMENT;
}
}
else
{
if (type == ShaderType::VERTEX)
{
ss[0]
I don't know why Cherno's ShaderProgramSource wasn't able to read my shader file, but it did after I follow your approach
these are really awesome :D
thanks mate :D
YO if you want to have multiple files like me, just seperate them and do this:
static std::string ParseShader(const std::string& file)
{
std::ifstream stream(file);
std::string line;
std::string shader = "";
while (getline(stream, line))
{
shader = shader + line;
shader = shader + "
";
}
return shader;
}
instead of returning a struct, return a string and then in the main do this:
std::string VertexSource = ParseShader("vertex.shader");
std::string FragmentSource = ParseShader("fragment.shader");
This is in my opinion cleaner way of doing things. DOnt forget the "
";, else it wont work.
Exactly what i was thinking of. I feel like putting it into one file is weird and in this case just overcomplicating stuff.
Thanks mate. Thats how you add valuable comment to a tutorial video.
@@bulentgercek I try to help out when I can. I really didn't see a reason to keep both shaders in the same file and then have all of this extra code especially for what was explained in the tutorial. Obviously Cherno is light-years ahead of me in opengl and c++. When I wrote this comment I was still in junior year of highschool and had very little understanding in both c++ and opengl. Now I guess I am better at c++ but my opengl hasn't improved all that much :/ so I'd take what I wrote here with a grain of salt. It will work but I can't tell you if it's the better approach.
In fact, looking back at this, it is definitely more performance demanding because it's calling parseShader twice. There is a workaround to that, just change the parameters to take in 2 strings and then do parallel read of both files.
Thank you for the series. Best content about the subject! Keep it up!
OpenGL is perhaps the most fun I am having learning something new in programming. Because I am also relearning C++ in the process. I will say, Rust is still my go-to language.
8:30 Oh joy!
The Cherno endorses FILE!
I like to use C as much as possible but when I have to use C++ I feel somewhat obliged to do things 'the C++ way'.
Of course that's nonsense, thanks for the reminder.
I wasted a bunch of time to write a preprocessor program that converts a shader file into a char*, so now I feel obligated to use that for my shaders.
I suppose it depends on whether you want to be able to change your shaders without recompiling... that's probably a good idea...
Thank's a lot for all your videos. Not easy to adapt with in visual studio code with mingw but it works ! I'm learnig a lot !
I added a little test in ParseShader :
if(type != ShaderType::NONE)
ss[(int) type]
thank you sir, that's why my code was giving it an error
hey can you tell me how you setup opengl in vscode ? I tried it myself a million times before downloading the bloated msvc to just get started with SOMETHING.
Well, I needed to add src before the path- so it was src/res...
Try to print the file out so You can find it easily
{
std::ifstream f("file.txt");
if (f.is_open())
std::cout
You've got an issue in the ParseShader (well not a problem here, but it can give errors in the future). If the first line of your shader doesn't contain #shader vertex of #shader fragment, it will try to access ss[-1]. Of course you can say the first line HAS to contain that, but even a comment (like copyright) could give you an error
Achim Vandierendonck this is explicit so if you write your shader wrong you are going to have an error, cuz you must specify the type of shader
I thought I was the only one who noticed. But yes that is a glaring error
I guess it was pretty clear that that's just a demo and a POC. Nobody would every write such a function in a serious production environment
yeah ran into exact this fault, as my first line was empty..
He actually adressed this on his Discord. The point of this video was just to show how you can combine shaders in one file, so he didn't really concern himself with that. So go ahead and add a fix for your code.
Took me a while to figure out that the getline was reading the entire file as one line, because the shader file end-of-line was set to CR. After I set it to CRLF it took it in line by line and it worker fine 👍
THANK YOU! I spent like 20 mins trying to work out this issue
You could use raw strings for shaders which would make it a lot cleaner than using a bunch of
(When not using files for them)
Yep it is simple and clean but there's still no syntax highlighting, error checks or code completion. For real shaders everyone should use files and error tagging.
for those struggling
instead of using: static void ParseShader(const std::string& filepath) {}
use: static ShaderProgramSource ParseShader(const std::string& filepath){}
and on return line: return ShaderProgramSource{ ss[0].str(), ss[1].str() };
as well as: ShaderProgramSource source = ParseShader("basic.shader");
(in main)
instead of: ShaderProgramSource source = ParseShader("res/shaders/basic.shader");
there is a better way anyway, also don't use const std string& for files, instead use std filesystem path which handles filepaths "natively"
If you're having trouble like me, the getline function is getting the whole file instead of one line, just add the delimiter on it. It'll be like: "while(getline(stream, line, '
'))"
wow, thanks a lot
damn thanks man
The problem is that I have not gone through the practices yet !
Sure you are amazing. Respect!
Hey so I'm pretty new to all this stuff, but I was wondering why (aside from comfort), do you combine the shaders into a single file. I like the idea of keeping things in separate files, and there seems to be a convention for GLSL file extensions (.frag, .vert, etc.). I know file reading is pretty slow, so it can be advantageous to minimize the amount of files that need to be read, but is that not avoidable with some sort of cache system?
Am I missing something?
in one video you have taught me so much on professional c++ programing than my entire life looking at stack overflow. so, does how you properly use struct, enums, sstreams, string, ftream nah I cant enumerate them all !thanks so much!!
Any timeline for you new Game Engine tutorial?
I don't think it's coming
lmao now... 11 months after your comment :3
I'm fangirl-ing every time anything works it's so interesting and cool
Is it normal that this triangle takes 60% gpu usage and 80% cpu? Like it's just 1 triangle. i5 and Rx580
@@luttinbuck413 Got to sleep!
... i mean, in your draw loop;)
i could listen to this man talk for hours
Interestingly if i leave the ';' on the end of the main functions when reading from file i get a shader compiler error
Same! I removed them, and no more problems : ) !
OH MY GOD YOU ARE A SAVIOR I was looking over my code because it would compile just fine but the triangle wouldn’t show up I tried this comment thinking it probably wouldn’t work but was worth a shot and it did thank you so much
getline isn't defined despite having string included.
Edit: never mind, it just took visual studio a very, very long time to figure out that i had included string (about 10 minutes).
Cherno: "Let's make it simple"
Also cherno: writes a parser
i'm not really good with OpenGL, but how all this time when learning i did it is basically made my own system that just splits one file into 2 parts whenever i type in the lines "@vertex" and "@frag", so basically it works the same way as reading the 2 files except i write everything in a single one, not sure if that's a good way but i'm about to find out :D
Update: i just watched the video and the only thing i used was the way to return 2 shaders at once, since i just had 2 different functions one to return the vertex one and another for the fragment
I ended up having to use this for my relative path being OpenGLChernoProject
es\shaders\Basic.shader
ShaderProgramSource source = parseShader("../res/shaders/Basic.shader");
It would be nice to be able to have separate files for shaders like in the video, but also to be able to have the shaders in the compile executable when the program is built...
00:18, You're not going to loose a hand when you only hit a cactus... xD
His beard is coming back.
He better keep it or I'm fucking unsubbing.
I'm kidding.
But he better fucking keep it.
@@loli42 and u are kidding
pretty cool stuff!
15:30 actually shouldn't he use a backslashes \ instead of a forward-slashes / in the filepath when he is working on windows?
(and not forget to escape the backslash in the string as
"res\\shaders\\Basic.shader")
And how do I make this protable so it uses / on unix and \ on windows?
you can use the linux and windows macros to detect whether you use / or \
For people using newer versions of Open GL, make two files ( one for vertex shader, one for fragment shader).Then read from
them and convert them into strings the same way he does. Two main functions don't compile for some reason.
remove any empty spaces from file - I am using a new version and it works fine
Can anyone tell me why this code is reading carriage returns from basic.shader as the ASCII code 12142? Needless to say, the shader doesn't compile.
Nice one, thanks!
Hey Bro! You are really cool! Thanks a lot for your videos!)
The triangle is still white and nothing gets written from the Basic.shader in my console. All the code is exactly the same with the same paths. I don't know what else to do
Also a white triangle for me. Weird that only one shader works.
Does anyone have any recommendations for the following warnings: C6385 and C6255 (this is for alloca, I just found on microsoft docs that it would be better to use malloca, which doesn't work for some reason)? For the C6385, I had to add an if statement:
if ((unsigned int)type
yeah i ran the program once got a red triangle then the it started not working randomly. and i got these errors. I just did what microsoft said and used _malloca then did what you said and now it all works again thank you for that if statement I don't understand it but it works.
You need to keep track of line offsets for the different shaders, so in case of a an error with a error line number, you can print out the real line in the .shader file...
I also learned how to read files..thanks
Somehow my While loop quits after the first line. Any ideas? Code is 100% identical to his..
EDIT: Fixed it. Somehow the getline function stored the whole file as 1 line. You can add a delim attribute to it that splits them into lines, like (getline(stream, line, '
')).
Thank Cherno for learning me how to debug. :}
Thank you so much!
Thank you, this was driving me crazy
Man I was struggling to figure out why the getline wasn't working like the while loop wasn't even running, turns out I was specifying the file extension incorrectly, in the file path I was typing in Basic.shaders, instead of Basic.shader
There is a minor exception unhandled.
ss[(int)type]
I have Included the Shader but my Compiler still using default shader and prints white Triangle instead of Red . Can someone help ?
Put your code in pastebin and send the link. I'll take a look
same thing with me too
NOOO! Cactus Carl! Cactus Carl has been cut from the series. : (
RIP
HOW COULD HE!!! UNSUBSCRIBED!!!
No matter what I do to the file path it always seems to yield a null file stream, noticed comments about filters in Visual studio but I cant seem to get the file to ever be read by getline command in the while loop
same issue. did you find a solution?
@@johndoe2790 i had a typo in my directory reference. - (capital letters)
Just a quick question. I followed your previous tutorial and managed to get a red triangle showing. After deciding to play with the code, I accidentally deleted the glDeleteShader() functions in CreateShaders, and the triangle became white again. How come? Is this something that is just how OpenGL works, and if it doesn't get a 'delete' command, aborts?
Your point about not having 2 seperate files for each shader does not makes to me. What if both your shaders are complex and big? Surely then it become annoying to navigate that one file it becomes too big?
Once a legend said "Actually , I might make a video on this "
I didn't want to create a struct just for the return so I just made it like this:
static void ParseShader(const std::string& filepath, std::string* pVertex, std::string* pFragment)
{
[...]
*pVertex = ss[0].str();
*pFragment = ss[1].str();
}
and called the function like this:
std::string vertexShader, fragmentShader;
ParseShader("res/shaders/basic.shader", &vertexShader, &fragmentShader);
I could use a bool as return which indicates if everything went fine but im lazy today
Dein Name ist zu lang.
@ICH WEISS....: (Ab)using parameters for return values is bad practice. With that approach, you could as well set them into some globals :P
@@sapuseven6119 Well, at least he didn't put it all into one word, as Germans tend to do :q
Hello, got an issue, when a compile, what returns to me it is a triangle with a basic shader, and on the prompt screen, gives me the error message, that could not compiler the shader, i dont´t know why but seems, that him cant find the path of file. In this case, what i need to do to fix this?
Im having a problem where my stream doesn't contain any information and cant read the file. What can I do?
My granny had that exact same couch. It was covered in plastic and she wouldn't let anybody sit on it. She smelled like dried prunes. Good riddance granny.
That awkward moment when you realize Granny's couch was a "Casting Couch"
Yes, my mother used it that way. She probably grew up in a family environment that should have been frugal. I'm sure she was removing the plastic on the couch when a visitor came. :) Frugal people. Respect.
17:19 Why not call the variable "program" too and not "shader"? That way it would be less tempting to use the wrong function.
I know im late but how do you get that colored text with shaders bcs every extension i use either doesn't work or it gives loads of errors!
I'm gonna bake the Basic.shader file as a resource into my EXE file since I set the configuration to put the exe file in a completely different directory, and even though while debugging the working directory is set to the ProjectDir for some reason the file isn't found by the ifstream object.
Usually people use .vert and .frag files for shaders code. VSCode has Shader Languages Support and GLSL Lint for these files.
what does the "ERROR: 0:6: 'gl_position': undeclared identifier" mean during the shader compile. Does anybody know how to solve that?
I am stuck with a white triangle only. Any help would be appreciated!
Same here
I know this is 4 years late but if anyone doing this now still gets a white triangle and it's because it's not reading your shader file, just delete the folders in the filepath and VS2019 will find it. So my filepath is literally "Base.shader" and it's working.
How did you return from static void? I needed to change it to return struct type.
Pretty good!
I tried to use ss[(int)type]
Mine was fixed after changing the ParseShader directory but now I have other problems
Same here! Was scrolling down the comments hoping someone would have encountered the same issue. Could you finally resolve it?
@@SreyRc No I gave up actually. This was my last video from this series
try:
"else if (type != ShaderType::NONE)
{
ss[(int)type]
hey guys, I had the same problem as you. Its happening because the ShaderType is defaulting to None, meaning its trying to read from ss[-1] which doesn't exist.
My solution was to replace the "else" statement in the while loop with:
else if (type == ShaderType::VERTEX || type == ShaderType::FRAGMENT)
{
ss[(int)type]
On recent GL/GLSL versions you can no longer combine multiple shaders into a single file, because if you try to compile a shader with _#shader__ [type]_ in the top of the file it will fail to compile
you could comment something though, no? //shader [type]
Personally, I'd rather keep them separate anyway.
sounds like you did it wrong, #shader shouldnt be put into the string stream, make sure you added it in the else statement
your mistake, you don't add that line into the string stream array buffer
Yeah you're probably right, I wasn't really good at programming back then :)
my while(getline(stream, line)) doesn't work. It doesn't even enter the while loop. I've tried std::getline(), help!
Joseph walker Do you get any errors? Your path may be wrong try checking that.
Nope the path is correct but i do get a compiler warning saying 's': unrecognized character escape sequence
Got it to work. I put the file path onto separate lines putting the name and then the slash on separate lines and it worked so i went back to on one line and it worked???
Joseph walker Oh i probably know the reason. There is a thing called escape sequence as you saw from the warning. You probably know about '
', it is the new line character and it is one of the few escape sequences. In your code you probably wrote \s somewhere and compiler tought that it was a escape sequence. There are two ways to work around this:
1) Replace \ with \\. \\ is also an escape sequence (ironically) and it means \.
2) Use / instead of \. In this video Cherno used / too.
You probably used the "wrong" slash when you first write the code. Then when you were putting the string into seperate lines you fixed the problem unintentionally.
Edit: Edited the format for readibility.
@@josephwalker208 Due! You almost made me flip my desk. Had same issue. Thanks!!!
Hi. If anyone has mood to answer this question, when I have several shaders, each has some attributes with same layout location, how can I tell OpenGL that this attribute belongs to that shader, or should I use the different layout locations for each of the attributes?
how did you comment out 2 lines at the same time 15:14?
alt-shift to select the lines then type away
Instead of enum class ShaderType, you can just add an int cnt;
if vertex cnt = 0;
if fragment cnt = 1;
Or just use a pointer to one of those strings and reset the pointer in the conditional to point to the other string, then use `(*currentString) +=` for appending to whatever string it currently points to :q No need for string streams.
IF you want to put both shader sources in one file it might be a good idea to name file .txt if you are having trouble with shader syntax highlighting extension errors.
I'm getting "No matching function for call to 'ParseShader" on Xcode...everything looks in place...any clue?
Having a strange error on my end. When I run the application i get an error that one of my shaders failed to compile. The strange thing is that the triangle appears with the correct color even with the error.
The error i get is "C7458: 'layout(location)' requires '#extension GL_ARB_separate_shader_objects : enable"
When i add this extension the shader compiles, but the triangle does not appear at all. Does this have to do with having 2 shaders in 1 file with recent versions of OpenGL?
Did you fix the error?
I had the same problem. My problem was that in the vertex shader the direction of the position vector was wrong. It should be "in", not "out":
layout(location = 0) in vec4 position;
I'm having trouble printing out the source code in Basic.Shader. My code is working up to the point where "while (getline(stream, line))" is called. the file path has made it's way into the ParseShader method, just for some reason the lines are not being read. So the problem has to lie between the ifstream and getline(stream, line). I'm running the latest OSX and Xcode, which is usually why I run into issues TheCherno does not have. Any help is greatly appreciated.
I had this issues, turns out you need to put the full filepath from /Users/username/..Path to your file
@@iamTLC You bloody lifesaver
I hope you already solved this one, but for any future visitors who have this particular issue: it could be an encoding thing. Different OSes use different line endings, which is known to cause problems with getline(). For instance, Windows uses both carriage return *and* newline ("
"), while Linux just uses newline ("
"). If you're running on a machine that only permits getline() to return on a Windows-style ending ("
") and you feed it a file that only contains Linux-style endings ("
"), it will not terminate until it hits EOF. In other words, the **entire file will be read as the first line, with no obvious errors**.
To be extra safe, just add an extra empty line between each line of shader code in your favorite text editor. OpenGL will ignore the empty lines, but you can be fairly sure that getline() will not.
@@iamTLC 3 years later and you're the person who saved me hours of headache, I hope life has done you well.
I know I'm 5 years late, but I was using "add filter" which was not the same as creating a new folder. You can either delete the bit before your file's name, or add the folders manually!
I have a problem when I try to compile: "invalid preprocessor command 'shader' ", someone can help me?
It's done, for the persons that have the same issue you need to open the properties of your shader file and in the item type put the property of "Does not participate in build" and the make sure that you open your file correctly
When I create folders in VS they don't map to the actual file-system. How does it work for you?
+Bern0d
I know this is late but thank you xD I'm rewatching these bits now and it's kinda clear to me this time around, lol.
I think there might be a better way to do this. What you need is to load the whole file as a string, then run it through a C pre-processor with some macros already defined that can filter out unwanted lines. There are some good C-preprocessors static libs out there.
Exactly what I would have done. And you get more bells and whistles with a C preprocessing as well.
Modern IDE's support .glsl format and can give quite a lot of useful information and highlight errors. Putting both shaders into 1 file makes it impossible.
However for a small project this is totally fine.
I've spent straight a whole day looking trough my source code wth was wrong... I wrote ShaderType type = ShaderType::FRAGMENT;
instead of type = ShaderType::FRAGMENT;
so I've been re-defining the instance of the class all this time xD
Great!
my code doesnt run as soon as i initialize the ShaderProgramSource object,help!!!!
Does anyone know what background music he's using for these videos?
I'm getting in the console window(the triangle appears white) :
Failed to compile vertexshader
ERROR: 0:8: ';' : syntax error syntax error
Failed to compile fragmentshader
ERROR: 0:8: ';' : syntax error syntax error
it's telling you,! you have syntax error...
CuRSeD thx, the discord people already helped me. What messed me up was the semicolon at the end of the main functions
Eli Howitt, thanks! You were spot on, I had to remove the semicolons after the main function. That was messing me up too! I'm on a Mac High Sierra, I also added
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
in order to use the 4.1 version of OpenGL.
Lol that merch joke 20:48
you forgot to close the file, and using separate files is way better:
- It maintains the consistency of one program is in one file.
- Someone else looking at your code might get confused.
- If you want to dynamically change the one of the shaders you'll have to load the file for one half of it?!
- Its reduces the code by allot
- No game engine that i know of will allow you to make a shader file and have two shaders in it.
Doesn't make sense, please stop this madness
"Its reduces the code by allot" no, it just splits it into 2 files. But I strongly agree with "If you want to dynamically change the one of the shaders you'll have to load the file for one half of it" and "No game engine that i know of will allow you to make a shader file and have two shaders in it".
Yep and from what i have seen he actually uses two different files for each shader in his github projects. It doesn't really matter and at this point its really easy to change the code to get shaders from different files
I'm just a novice programmer but to me, reading in codes from a file at runtime that are actually executed without thoroughly checking the contents seems flawed to me. Huge security issue.
Those shader codes don't change during runtime, right? Why not import during compile time with some compiler directives? Seems way more safe to me. Buy I might be missing something huge of course.
well, imagine having a big project with compilation times more then 5 - 10 mins. imagine you wanna tweak something in one of your shaders. most of your working day will be spent waiting for compilation :D
Was testing it the way you did incorrect in some cases? In my case nothing prints... I have already rewatched once... Anyway maybe I did something wrong
I thought I'd followed this exactly, but when I guess my shader file is being parsed incorrectly, as it doesn't work and the cout prints
#version 330 core1214212142layout(location = 0) in vec4 position;1214212142void main()12142{12142 gl_Position = position;12142}1214212142
My gut says that I've used an incorrect data type somewhere and it's filling the VertexSource string with junk... but I actually have no idea.
I worked out my error, it was silly. I wrote
ss[(int)type]
@@Gr0nal thank you so much... I am coming from c#, with NO c++ history so this is like a culture shock to me lol
I tried putting up the same code as cherno did but i could not work out how to seperate one file into two seperate strings based on what cherno wrote,.. so after a lot of tryings, i managed to create two seperate files for vertex and fragment shaders .. and worked it out as i know best .. hope its not a problem tho