From f4a00bb843ee5e01dd9911f98b7a59a7343c34c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4ger?= Date: Wed, 20 Sep 2023 15:35:19 +0200 Subject: [PATCH 1/2] un-oop:ed the Shader class --- Chapter1/2-HelloTriangle/Shaders/shader.vert | 8 +- Chapter1/2-HelloTriangle/Window.cs | 4 +- .../Shaders/shader.vert | 4 +- Chapter1/3-ElementBufferObjects/Window.cs | 4 +- .../4-Shaders-InsAndOuts/Shaders/shader.vert | 4 +- Chapter1/4-Shaders-InsAndOuts/Window.cs | 5 +- .../Shaders/shader.vert | 4 +- Chapter1/4-Shaders-MoreAttributes/Window.cs | 4 +- .../4-Shaders-Uniforms/Shaders/shader.vert | 4 +- Chapter1/4-Shaders-Uniforms/Window.cs | 4 +- Chapter1/5-Textures/Shaders/shader.vert | 4 +- Chapter1/5-Textures/Window.cs | 8 +- .../6-MultipleTextures/Shaders/shader.vert | 4 +- Chapter1/6-MultipleTextures/Window.cs | 12 +- .../7-Transformations/Shaders/shader.vert | 4 +- Chapter1/7-Transformations/Window.cs | 14 +- .../8-CoordinatesSystems/Shaders/shader.vert | 4 +- Chapter1/8-CoordinatesSystems/Window.cs | 20 +-- Chapter1/9-Camera/Shaders/shader.vert | 4 +- Chapter1/9-Camera/Window.cs | 23 +-- Chapter2/1-Colors/Window.cs | 37 +++-- Chapter2/2-BasicLighting/Window.cs | 43 ++--- Chapter2/3-Materials/Window.cs | 48 +++--- Chapter2/4-LightingMaps/Shaders/lighting.frag | 8 +- Chapter2/4-LightingMaps/Shaders/shader.vert | 6 +- Chapter2/4-LightingMaps/Window.cs | 53 +++--- .../5-LightCasters-DirectionalLights.csproj | 12 ++ .../Shaders/lighting.frag | 8 +- .../Shaders/shader.vert | 6 +- .../Window.cs | 51 +++--- .../5-LightCasters-PointLights.csproj | 12 ++ .../Shaders/lighting.frag | 8 +- .../Shaders/shader.vert | 6 +- Chapter2/5-LightCasters-PointLights/Window.cs | 55 ++++--- .../Shaders/lighting.frag | 8 +- .../Shaders/shader.vert | 6 +- Chapter2/5-LightCasters-Spotlight/Window.cs | 61 +++---- .../6-MultipleLights/Shaders/lighting.frag | 20 +-- Chapter2/6-MultipleLights/Shaders/shader.vert | 6 +- Chapter2/6-MultipleLights/Window.cs | 81 +++++----- Common/Shader.cs | 151 ++++++------------ 41 files changed, 416 insertions(+), 412 deletions(-) diff --git a/Chapter1/2-HelloTriangle/Shaders/shader.vert b/Chapter1/2-HelloTriangle/Shaders/shader.vert index e9e0e7b..6ebfb4e 100644 --- a/Chapter1/2-HelloTriangle/Shaders/shader.vert +++ b/Chapter1/2-HelloTriangle/Shaders/shader.vert @@ -18,14 +18,14 @@ // shader(vertex) -// This defines our input variable, aPosition. +// This defines our input variable, aPos. // It starts with the line "layout(location = 0)". This defines where this input variable will be located, which is needed for GL.VertexAttribPointer. -// However, you can omit it, and replace this with just "in vec3 aPosition". If you do that, you'll have to replace the 0 in GL.VertexAttribPointer with +// However, you can omit it, and replace this with just "in vec3 aPos". If you do that, you'll have to replace the 0 in GL.VertexAttribPointer with // a call to GL.GetAttribLocation(shaderHandle, attributeName) // Next, the keyword "in" defines this as an input variable. We'll have an example of the "out" keyword in the next tutorial. // Then, the keyword "vec3" means this is a vector with 3 floats inside. -layout(location = 0) in vec3 aPosition; +layout(location = 0) in vec3 aPos; // Like C, we have an entrypoint function. In this case, it takes void and returns void, and must be named main. @@ -37,5 +37,5 @@ layout(location = 0) in vec3 aPosition; void main(void) { - gl_Position = vec4(aPosition, 1.0); + gl_Position = vec4(aPos, 1.0); } \ No newline at end of file diff --git a/Chapter1/2-HelloTriangle/Window.cs b/Chapter1/2-HelloTriangle/Window.cs index 133aa2d..e37c319 100644 --- a/Chapter1/2-HelloTriangle/Window.cs +++ b/Chapter1/2-HelloTriangle/Window.cs @@ -118,7 +118,7 @@ protected override void OnLoad() // Now, enable the shader. // Just like the VBO, this is global, so every function that uses a shader will modify this one until a new one is bound instead. - _shader.Use(); + GL.UseProgram(_shader.Handle); // Setup is now complete! Now we move to the OnRenderFrame function to finally draw the triangle. } @@ -140,7 +140,7 @@ protected override void OnRenderFrame(FrameEventArgs e) // and then calling an OpenGL function to render. // Bind the shader - _shader.Use(); + GL.UseProgram(_shader.Handle); // Bind the VAO GL.BindVertexArray(_vertexArrayObject); diff --git a/Chapter1/3-ElementBufferObjects/Shaders/shader.vert b/Chapter1/3-ElementBufferObjects/Shaders/shader.vert index 42a0e96..0a3cec8 100644 --- a/Chapter1/3-ElementBufferObjects/Shaders/shader.vert +++ b/Chapter1/3-ElementBufferObjects/Shaders/shader.vert @@ -1,8 +1,8 @@ #version 330 core -layout(location = 0) in vec3 aPosition; +layout(location = 0) in vec3 aPos; void main(void) { - gl_Position = vec4(aPosition, 1.0); + gl_Position = vec4(aPos, 1.0); } \ No newline at end of file diff --git a/Chapter1/3-ElementBufferObjects/Window.cs b/Chapter1/3-ElementBufferObjects/Window.cs index 012f8d8..92539f3 100644 --- a/Chapter1/3-ElementBufferObjects/Window.cs +++ b/Chapter1/3-ElementBufferObjects/Window.cs @@ -77,7 +77,7 @@ protected override void OnLoad() // The EBO has now been properly setup. Go to the Render function to see how we draw our rectangle now! _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); - _shader.Use(); + GL.UseProgram(_shader.Handle); } protected override void OnRenderFrame(FrameEventArgs e) @@ -86,7 +86,7 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.Clear(ClearBufferMask.ColorBufferBit); - _shader.Use(); + GL.UseProgram(_shader.Handle); // Because ElementArrayObject is a property of the currently bound VAO, // the buffer you will find in the ElementArrayBuffer will change with the currently bound VAO. diff --git a/Chapter1/4-Shaders-InsAndOuts/Shaders/shader.vert b/Chapter1/4-Shaders-InsAndOuts/Shaders/shader.vert index cb39b32..c87b6e7 100644 --- a/Chapter1/4-Shaders-InsAndOuts/Shaders/shader.vert +++ b/Chapter1/4-Shaders-InsAndOuts/Shaders/shader.vert @@ -1,7 +1,7 @@ #version 330 core // the position variable has attribute position 0 -layout(location = 0) in vec3 aPosition; +layout(location = 0) in vec3 aPos; // This variable uses the keyword out in order to pass on the value to the // next shader down in the chain, in this case the frag shader @@ -10,7 +10,7 @@ out vec4 vertexColor; void main(void) { // see how we directly give a vec3 to vec4's constructor - gl_Position = vec4(aPosition, 1.0); + gl_Position = vec4(aPos, 1.0); // Here we assign the variable a dark red color to the out variable vertexColor = vec4(0.5, 0.0, 0.0, 1.0); diff --git a/Chapter1/4-Shaders-InsAndOuts/Window.cs b/Chapter1/4-Shaders-InsAndOuts/Window.cs index dd2f4f0..5ca3951 100644 --- a/Chapter1/4-Shaders-InsAndOuts/Window.cs +++ b/Chapter1/4-Shaders-InsAndOuts/Window.cs @@ -57,7 +57,8 @@ protected override void OnLoad() Debug.WriteLine($"Maximum number of vertex attributes supported: {maxAttributeCount}"); _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); - _shader.Use(); + + GL.UseProgram(_shader.Handle); } protected override void OnRenderFrame(FrameEventArgs e) @@ -66,7 +67,7 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.Clear(ClearBufferMask.ColorBufferBit); - _shader.Use(); + GL.UseProgram(_shader.Handle); GL.BindVertexArray(_vertexArrayObject); diff --git a/Chapter1/4-Shaders-MoreAttributes/Shaders/shader.vert b/Chapter1/4-Shaders-MoreAttributes/Shaders/shader.vert index 364b96f..ada856b 100644 --- a/Chapter1/4-Shaders-MoreAttributes/Shaders/shader.vert +++ b/Chapter1/4-Shaders-MoreAttributes/Shaders/shader.vert @@ -1,7 +1,7 @@ #version 330 core // the position variable has attribute position 0 -layout(location = 0) in vec3 aPosition; +layout(location = 0) in vec3 aPos; // This is where the color values we assigned in the main program goes to layout(location = 1) in vec3 aColor; @@ -11,7 +11,7 @@ out vec3 ourColor; // output a color to the fragment shader void main(void) { // see how we directly give a vec3 to vec4's constructor - gl_Position = vec4(aPosition, 1.0); + gl_Position = vec4(aPos, 1.0); // We use the outColor variable to pass on the color information to the frag shader ourColor = aColor; diff --git a/Chapter1/4-Shaders-MoreAttributes/Window.cs b/Chapter1/4-Shaders-MoreAttributes/Window.cs index 53d8985..279d094 100644 --- a/Chapter1/4-Shaders-MoreAttributes/Window.cs +++ b/Chapter1/4-Shaders-MoreAttributes/Window.cs @@ -68,7 +68,7 @@ protected override void OnLoad() Debug.WriteLine($"Maximum number of vertex attributes supported: {maxAttributeCount}"); _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); - _shader.Use(); + GL.UseProgram(_shader.Handle); } protected override void OnRenderFrame(FrameEventArgs e) @@ -77,7 +77,7 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.Clear(ClearBufferMask.ColorBufferBit); - _shader.Use(); + GL.UseProgram(_shader.Handle); GL.BindVertexArray(_vertexArrayObject); diff --git a/Chapter1/4-Shaders-Uniforms/Shaders/shader.vert b/Chapter1/4-Shaders-Uniforms/Shaders/shader.vert index bb42695..a86fec7 100644 --- a/Chapter1/4-Shaders-Uniforms/Shaders/shader.vert +++ b/Chapter1/4-Shaders-Uniforms/Shaders/shader.vert @@ -1,9 +1,9 @@ #version 330 core -layout(location = 0) in vec3 aPosition; // the position variable has attribute position 0 +layout(location = 0) in vec3 aPos; // the position variable has attribute position 0 void main(void) { // see how we directly give a vec3 to vec4's constructor - gl_Position = vec4(aPosition, 1.0); + gl_Position = vec4(aPos, 1.0); } \ No newline at end of file diff --git a/Chapter1/4-Shaders-Uniforms/Window.cs b/Chapter1/4-Shaders-Uniforms/Window.cs index ece406d..a09f956 100644 --- a/Chapter1/4-Shaders-Uniforms/Window.cs +++ b/Chapter1/4-Shaders-Uniforms/Window.cs @@ -57,7 +57,7 @@ protected override void OnLoad() Debug.WriteLine($"Maximum number of vertex attributes supported: {maxAttributeCount}"); _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); - _shader.Use(); + GL.UseProgram(_shader.Handle); // We start the stopwatch here as this method is only called once. _timer = new Stopwatch(); @@ -70,7 +70,7 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.Clear(ClearBufferMask.ColorBufferBit); - _shader.Use(); + GL.UseProgram(_shader.Handle); // Here, we get the total seconds that have elapsed since the last time this method has reset // and we assign it to the timeValue variable so it can be used for the pulsating color. diff --git a/Chapter1/5-Textures/Shaders/shader.vert b/Chapter1/5-Textures/Shaders/shader.vert index 494f81d..85c3668 100644 --- a/Chapter1/5-Textures/Shaders/shader.vert +++ b/Chapter1/5-Textures/Shaders/shader.vert @@ -1,6 +1,6 @@ #version 330 core -layout(location = 0) in vec3 aPosition; +layout(location = 0) in vec3 aPos; // We add another input variable for the texture coordinates. @@ -18,5 +18,5 @@ void main(void) texCoord = aTexCoord; - gl_Position = vec4(aPosition, 1.0); + gl_Position = vec4(aPos, 1.0); } \ No newline at end of file diff --git a/Chapter1/5-Textures/Window.cs b/Chapter1/5-Textures/Window.cs index e8739a3..71f2df6 100644 --- a/Chapter1/5-Textures/Window.cs +++ b/Chapter1/5-Textures/Window.cs @@ -61,19 +61,19 @@ protected override void OnLoad() // The shaders have been modified to include the texture coordinates, check them out after finishing the OnLoad function. _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); - _shader.Use(); + GL.UseProgram(_shader.Handle); // Because there's now 5 floats between the start of the first vertex and the start of the second, // we modify the stride from 3 * sizeof(float) to 5 * sizeof(float). // This will now pass the new vertex array to the buffer. - var vertexLocation = _shader.GetAttribLocation("aPosition"); + var vertexLocation = 0; // The location of aPos GL.EnableVertexAttribArray(vertexLocation); GL.VertexAttribPointer(vertexLocation, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0); // Next, we also setup texture coordinates. It works in much the same way. // We add an offset of 3, since the texture coordinates comes after the position data. // We also change the amount of data to 2 because there's only 2 floats for texture coordinates. - var texCoordLocation = _shader.GetAttribLocation("aTexCoord"); + var texCoordLocation = 1; // The location of aTexCoord GL.EnableVertexAttribArray(texCoordLocation); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); @@ -90,7 +90,7 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vertexArrayObject); _texture.Use(TextureUnit.Texture0); - _shader.Use(); + GL.UseProgram(_shader.Handle); GL.DrawElements(PrimitiveType.Triangles, _indices.Length, DrawElementsType.UnsignedInt, 0); diff --git a/Chapter1/6-MultipleTextures/Shaders/shader.vert b/Chapter1/6-MultipleTextures/Shaders/shader.vert index 4fb2871..4934eaa 100644 --- a/Chapter1/6-MultipleTextures/Shaders/shader.vert +++ b/Chapter1/6-MultipleTextures/Shaders/shader.vert @@ -1,6 +1,6 @@ #version 330 core -layout(location = 0) in vec3 aPosition; +layout(location = 0) in vec3 aPos; layout(location = 1) in vec2 aTexCoord; @@ -10,5 +10,5 @@ void main(void) { texCoord = aTexCoord; - gl_Position = vec4(aPosition, 1.0); + gl_Position = vec4(aPos, 1.0); } \ No newline at end of file diff --git a/Chapter1/6-MultipleTextures/Window.cs b/Chapter1/6-MultipleTextures/Window.cs index 6b19d83..eeac115 100644 --- a/Chapter1/6-MultipleTextures/Window.cs +++ b/Chapter1/6-MultipleTextures/Window.cs @@ -59,13 +59,13 @@ protected override void OnLoad() // shader.frag has been modified yet again, take a look at it as well. _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); - _shader.Use(); + GL.UseProgram(_shader.Handle); - var vertexLocation = _shader.GetAttribLocation("aPosition"); + var vertexLocation = 0; // The location of aPos GL.EnableVertexAttribArray(vertexLocation); GL.VertexAttribPointer(vertexLocation, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0); - var texCoordLocation = _shader.GetAttribLocation("aTexCoord"); + var texCoordLocation = 1; // The location of aTexCoord GL.EnableVertexAttribArray(texCoordLocation); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); @@ -81,8 +81,8 @@ protected override void OnLoad() // Next, we must setup the samplers in the shaders to use the right textures. // The int we send to the uniform indicates which texture unit the sampler should use. - _shader.SetInt("texture0", 0); - _shader.SetInt("texture1", 1); + GL.Uniform1(_shader.UniformLocations["texture0"], 0); + GL.Uniform1(_shader.UniformLocations["texture1"], 1); } protected override void OnRenderFrame(FrameEventArgs e) @@ -95,7 +95,7 @@ protected override void OnRenderFrame(FrameEventArgs e) _texture.Use(TextureUnit.Texture0); _texture2.Use(TextureUnit.Texture1); - _shader.Use(); + GL.UseProgram(_shader.Handle); GL.DrawElements(PrimitiveType.Triangles, _indices.Length, DrawElementsType.UnsignedInt, 0); diff --git a/Chapter1/7-Transformations/Shaders/shader.vert b/Chapter1/7-Transformations/Shaders/shader.vert index bb064b4..77ba190 100644 --- a/Chapter1/7-Transformations/Shaders/shader.vert +++ b/Chapter1/7-Transformations/Shaders/shader.vert @@ -1,6 +1,6 @@ #version 330 core -layout(location = 0) in vec3 aPosition; +layout(location = 0) in vec3 aPos; layout(location = 1) in vec2 aTexCoord; @@ -14,5 +14,5 @@ void main(void) texCoord = aTexCoord; // Then all you have to do is multiply the vertices by the transformation matrix, and you'll see your transformation in the scene! - gl_Position = vec4(aPosition, 1.0) * transform; + gl_Position = vec4(aPos, 1.0) * transform; } \ No newline at end of file diff --git a/Chapter1/7-Transformations/Window.cs b/Chapter1/7-Transformations/Window.cs index 2507132..f65e766 100644 --- a/Chapter1/7-Transformations/Window.cs +++ b/Chapter1/7-Transformations/Window.cs @@ -69,13 +69,13 @@ protected override void OnLoad() // shader.vert has been modified, take a look at it as well. _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); - _shader.Use(); + GL.UseProgram(_shader.Handle); - var vertexLocation = _shader.GetAttribLocation("aPosition"); + var vertexLocation = 0; // The location of aPos GL.EnableVertexAttribArray(vertexLocation); GL.VertexAttribPointer(vertexLocation, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0); - var texCoordLocation = _shader.GetAttribLocation("aTexCoord"); + var texCoordLocation = 1; // The location of aTexCoord GL.EnableVertexAttribArray(texCoordLocation); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); @@ -85,8 +85,8 @@ protected override void OnLoad() _texture2 = Texture.LoadFromFile("Resources/awesomeface.png"); _texture2.Use(TextureUnit.Texture1); - _shader.SetInt("texture0", 0); - _shader.SetInt("texture1", 1); + GL.Uniform1(_shader.UniformLocations["texture0"], 0); + GL.Uniform1(_shader.UniformLocations["texture1"], 1); } protected override void OnRenderFrame(FrameEventArgs e) @@ -125,11 +125,11 @@ protected override void OnRenderFrame(FrameEventArgs e) _texture.Use(TextureUnit.Texture0); _texture2.Use(TextureUnit.Texture1); - _shader.Use(); + GL.UseProgram(_shader.Handle); // Now that the matrix is finished, pass it to the vertex shader. // Go over to shader.vert to see how we finally apply this to the vertices. - _shader.SetMatrix4("transform", transform); + GL.UniformMatrix4(_shader.UniformLocations["transform"], true, ref transform); // And that's it for now! In the next tutorial, we'll see how to setup a full coordinates system. diff --git a/Chapter1/8-CoordinatesSystems/Shaders/shader.vert b/Chapter1/8-CoordinatesSystems/Shaders/shader.vert index 6457b69..a1dd2e5 100644 --- a/Chapter1/8-CoordinatesSystems/Shaders/shader.vert +++ b/Chapter1/8-CoordinatesSystems/Shaders/shader.vert @@ -1,6 +1,6 @@ #version 330 core -layout(location = 0) in vec3 aPosition; +layout(location = 0) in vec3 aPos; layout(location = 1) in vec2 aTexCoord; @@ -14,5 +14,5 @@ void main(void) { texCoord = aTexCoord; - gl_Position = vec4(aPosition, 1.0) * model * view * projection; + gl_Position = vec4(aPos, 1.0) * model * view * projection; } diff --git a/Chapter1/8-CoordinatesSystems/Window.cs b/Chapter1/8-CoordinatesSystems/Window.cs index 3282234..d45e6cc 100644 --- a/Chapter1/8-CoordinatesSystems/Window.cs +++ b/Chapter1/8-CoordinatesSystems/Window.cs @@ -79,13 +79,13 @@ protected override void OnLoad() // shader.vert has been modified. Take a look at it after the explanation in OnRenderFrame. _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); - _shader.Use(); + GL.UseProgram(_shader.Handle); - var vertexLocation = _shader.GetAttribLocation("aPosition"); + var vertexLocation = 0; // The location of aPos GL.EnableVertexAttribArray(vertexLocation); GL.VertexAttribPointer(vertexLocation, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0); - var texCoordLocation = _shader.GetAttribLocation("aTexCoord"); + var texCoordLocation = 1; // The location of aTexCoord GL.EnableVertexAttribArray(texCoordLocation); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); @@ -95,8 +95,8 @@ protected override void OnLoad() _texture2 = Texture.LoadFromFile("Resources/awesomeface.png"); _texture2.Use(TextureUnit.Texture1); - _shader.SetInt("texture0", 0); - _shader.SetInt("texture1", 1); + GL.Uniform1(_shader.UniformLocations["texture0"], 0); + GL.Uniform1(_shader.UniformLocations["texture1"], 1); // For the view, we don't do too much here. Next tutorial will be all about a Camera class that will make it much easier to manipulate the view. // For now, we move it backwards three units on the Z axis. @@ -126,10 +126,10 @@ protected override void OnRenderFrame(FrameEventArgs e) _texture.Use(TextureUnit.Texture0); _texture2.Use(TextureUnit.Texture1); - _shader.Use(); + GL.UseProgram(_shader.Handle); // Finally, we have the model matrix. This determines the position of the model. - var model = Matrix4.Identity * Matrix4.CreateRotationX((float)MathHelper.DegreesToRadians(_time)); + var model = Matrix4.CreateRotationX((float)MathHelper.DegreesToRadians(_time)); // Then, we pass all of these matrices to the vertex shader. // You could also multiply them here and then pass, which is faster, but having the separate matrices available is used for some advanced effects. @@ -140,9 +140,9 @@ protected override void OnRenderFrame(FrameEventArgs e) // If you pass the individual matrices to the shader and multiply there, you have to do in the order "model * view * projection". // You can think like this: first apply the modelToWorld (aka model) matrix, then apply the worldToView (aka view) matrix, // and finally apply the viewToProjectedSpace (aka projection) matrix. - _shader.SetMatrix4("model", model); - _shader.SetMatrix4("view", _view); - _shader.SetMatrix4("projection", _projection); + GL.UniformMatrix4(_shader.UniformLocations["model"], true, ref model); + GL.UniformMatrix4(_shader.UniformLocations["view"], true, ref _view); + GL.UniformMatrix4(_shader.UniformLocations["projection"], true, ref _projection); GL.DrawElements(PrimitiveType.Triangles, _indices.Length, DrawElementsType.UnsignedInt, 0); diff --git a/Chapter1/9-Camera/Shaders/shader.vert b/Chapter1/9-Camera/Shaders/shader.vert index 6457b69..a1dd2e5 100644 --- a/Chapter1/9-Camera/Shaders/shader.vert +++ b/Chapter1/9-Camera/Shaders/shader.vert @@ -1,6 +1,6 @@ #version 330 core -layout(location = 0) in vec3 aPosition; +layout(location = 0) in vec3 aPos; layout(location = 1) in vec2 aTexCoord; @@ -14,5 +14,5 @@ void main(void) { texCoord = aTexCoord; - gl_Position = vec4(aPosition, 1.0) * model * view * projection; + gl_Position = vec4(aPos, 1.0) * model * view * projection; } diff --git a/Chapter1/9-Camera/Window.cs b/Chapter1/9-Camera/Window.cs index f9ccc1f..6c8530e 100644 --- a/Chapter1/9-Camera/Window.cs +++ b/Chapter1/9-Camera/Window.cs @@ -85,13 +85,13 @@ protected override void OnLoad() GL.BufferData(BufferTarget.ElementArrayBuffer, _indices.Length * sizeof(uint), _indices, BufferUsageHint.StaticDraw); _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); - _shader.Use(); + GL.UseProgram(_shader.Handle); - var vertexLocation = _shader.GetAttribLocation("aPosition"); + var vertexLocation = 0; // The location of aPos GL.EnableVertexAttribArray(vertexLocation); GL.VertexAttribPointer(vertexLocation, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0); - var texCoordLocation = _shader.GetAttribLocation("aTexCoord"); + var texCoordLocation = 1; // The location of aTexCoord GL.EnableVertexAttribArray(texCoordLocation); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); @@ -101,8 +101,8 @@ protected override void OnLoad() _texture2 = Texture.LoadFromFile("Resources/awesomeface.png"); _texture2.Use(TextureUnit.Texture1); - _shader.SetInt("texture0", 0); - _shader.SetInt("texture1", 1); + GL.Uniform1(_shader.UniformLocations["texture0"], 0); + GL.Uniform1(_shader.UniformLocations["texture1"], 1); // We initialize the camera so that it is 3 units back from where the rectangle is. // We also give it the proper aspect ratio. @@ -124,12 +124,15 @@ protected override void OnRenderFrame(FrameEventArgs e) _texture.Use(TextureUnit.Texture0); _texture2.Use(TextureUnit.Texture1); - _shader.Use(); + GL.UseProgram(_shader.Handle); - var model = Matrix4.Identity * Matrix4.CreateRotationX((float)MathHelper.DegreesToRadians(_time)); - _shader.SetMatrix4("model", model); - _shader.SetMatrix4("view", _camera.GetViewMatrix()); - _shader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + Matrix4 projection = _camera.GetProjectionMatrix(); + Matrix4 view = _camera.GetViewMatrix(); + + var model = Matrix4.CreateRotationX((float)MathHelper.DegreesToRadians(_time)); + GL.UniformMatrix4(_shader.UniformLocations["model"], true, ref model); + GL.UniformMatrix4(_shader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_shader.UniformLocations["projection"], true, ref projection); GL.DrawElements(PrimitiveType.Triangles, _indices.Length, DrawElementsType.UnsignedInt, 0); diff --git a/Chapter2/1-Colors/Window.cs b/Chapter2/1-Colors/Window.cs index 69715a4..97614af 100644 --- a/Chapter2/1-Colors/Window.cs +++ b/Chapter2/1-Colors/Window.cs @@ -4,6 +4,7 @@ using OpenTK.Windowing.Common; using OpenTK.Windowing.GraphicsLibraryFramework; using OpenTK.Windowing.Desktop; +using OpenTK.Graphics.GL; namespace LearnOpenTK { @@ -115,7 +116,8 @@ protected override void OnLoad() _vaoModel = GL.GenVertexArray(); GL.BindVertexArray(_vaoModel); - var vertexLocation = _lightingShader.GetAttribLocation("aPos"); + // Specified in the shader.vert file, aPos has location 0. + var vertexLocation = 0; GL.EnableVertexAttribArray(vertexLocation); GL.VertexAttribPointer(vertexLocation, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0); } @@ -125,8 +127,8 @@ protected override void OnLoad() _vaoLamp = GL.GenVertexArray(); GL.BindVertexArray(_vaoLamp); - // Set the vertex attributes (only position data for our lamp) - var vertexLocation = _lampShader.GetAttribLocation("aPos"); + // Specified in the shader.vert file, aPos has location 0. + var vertexLocation = 0; GL.EnableVertexAttribArray(vertexLocation); GL.VertexAttribPointer(vertexLocation, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0); } @@ -145,29 +147,34 @@ protected override void OnRenderFrame(FrameEventArgs e) // Draw the model/cube with the lighting shader GL.BindVertexArray(_vaoModel); - _lightingShader.Use(); + GL.UseProgram(_lightingShader.Handle); + + Matrix4 projection = _camera.GetProjectionMatrix(); + Matrix4 view = _camera.GetViewMatrix(); // Matrix4.Identity is used as the matrix, since we just want to draw it at 0, 0, 0 - _lightingShader.SetMatrix4("model", Matrix4.Identity); - _lightingShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lightingShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + Matrix4 model = Matrix4.Identity; + + GL.UniformMatrix4(_lightingShader.UniformLocations["model"], true, ref model); + GL.UniformMatrix4(_lightingShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lightingShader.UniformLocations["projection"], true, ref projection); - _lightingShader.SetVector3("objectColor", new Vector3(1.0f, 0.5f, 0.31f)); - _lightingShader.SetVector3("lightColor", new Vector3(1.0f, 1.0f, 1.0f)); + GL.Uniform3(_lightingShader.UniformLocations["objectColor"], new Vector3(1.0f, 0.5f, 0.31f)); + GL.Uniform3(_lightingShader.UniformLocations["lightColor"], new Vector3(1.0f, 1.0f, 1.0f)); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); // Draw the lamp, this is mostly the same as for the model cube GL.BindVertexArray(_vaoLamp); - _lampShader.Use(); + GL.UseProgram(_lampShader.Handle); - Matrix4 lampMatrix = Matrix4.CreateScale(0.2f); // We scale the lamp cube down a bit to make it less dominant - lampMatrix = lampMatrix * Matrix4.CreateTranslation(_lightPos); + // We scale the lamp cube down a bit to make it less dominant + Matrix4 lampMatrix = Matrix4.CreateScale(0.2f) * Matrix4.CreateTranslation(_lightPos); - _lampShader.SetMatrix4("model", lampMatrix); - _lampShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lampShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + GL.UniformMatrix4(_lampShader.UniformLocations["model"], true, ref lampMatrix); + GL.UniformMatrix4(_lampShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lampShader.UniformLocations["projection"], true, ref projection); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); diff --git a/Chapter2/2-BasicLighting/Window.cs b/Chapter2/2-BasicLighting/Window.cs index d80d979..67babc2 100644 --- a/Chapter2/2-BasicLighting/Window.cs +++ b/Chapter2/2-BasicLighting/Window.cs @@ -4,6 +4,7 @@ using OpenTK.Windowing.Common; using OpenTK.Windowing.GraphicsLibraryFramework; using OpenTK.Windowing.Desktop; +using OpenTK.Graphics.GL; namespace LearnOpenTK { @@ -103,13 +104,14 @@ protected override void OnLoad() _vaoModel = GL.GenVertexArray(); GL.BindVertexArray(_vaoModel); - var positionLocation = _lightingShader.GetAttribLocation("aPos"); + // Specified in the shader.vert file, aPos has location 0. + var positionLocation = 0; GL.EnableVertexAttribArray(positionLocation); // Remember to change the stride as we now have 6 floats per vertex GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), 0); - // We now need to define the layout of the normal so the shader can use it - var normalLocation = _lightingShader.GetAttribLocation("aNormal"); + // Specified in the shader.vert file, aNormal has location 1. + var normalLocation = 1; GL.EnableVertexAttribArray(normalLocation); GL.VertexAttribPointer(normalLocation, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), 3 * sizeof(float)); } @@ -118,7 +120,8 @@ protected override void OnLoad() _vaoLamp = GL.GenVertexArray(); GL.BindVertexArray(_vaoLamp); - var positionLocation = _lampShader.GetAttribLocation("aPos"); + // Specified in the shader.vert file, aPos has location 0. + var positionLocation = 0; GL.EnableVertexAttribArray(positionLocation); // Also change the stride here as we now have 6 floats per vertex. Now we don't define the normal for the lamp VAO // this is because it isn't used, it might seem like a waste to use the same VBO if they dont have the same data @@ -140,29 +143,33 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vaoModel); - _lightingShader.Use(); + GL.UseProgram(_lightingShader.Handle); - _lightingShader.SetMatrix4("model", Matrix4.Identity); - _lightingShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lightingShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + Matrix4 projection = _camera.GetProjectionMatrix(); + Matrix4 view = _camera.GetViewMatrix(); - _lightingShader.SetVector3("objectColor", new Vector3(1.0f, 0.5f, 0.31f)); - _lightingShader.SetVector3("lightColor", new Vector3(1.0f, 1.0f, 1.0f)); - _lightingShader.SetVector3("lightPos", _lightPos); - _lightingShader.SetVector3("viewPos", _camera.Position); + Matrix4 model = Matrix4.Identity; + + GL.UniformMatrix4(_lightingShader.UniformLocations["model"], true, ref model); + GL.UniformMatrix4(_lightingShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lightingShader.UniformLocations["projection"], true, ref projection); + + GL.Uniform3(_lightingShader.UniformLocations["objectColor"], new Vector3(1.0f, 0.5f, 0.31f)); + GL.Uniform3(_lightingShader.UniformLocations["lightColor"], new Vector3(1.0f, 1.0f, 1.0f)); + GL.Uniform3(_lightingShader.UniformLocations["lightPos"], _lightPos); + GL.Uniform3(_lightingShader.UniformLocations["viewPos"], _camera.Position); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); GL.BindVertexArray(_vaoLamp); - _lampShader.Use(); + GL.UseProgram(_lampShader.Handle); - Matrix4 lampMatrix = Matrix4.CreateScale(0.2f); - lampMatrix = lampMatrix * Matrix4.CreateTranslation(_lightPos); + Matrix4 lampMatrix = Matrix4.CreateScale(0.2f) * Matrix4.CreateTranslation(_lightPos); - _lampShader.SetMatrix4("model", lampMatrix); - _lampShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lampShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + GL.UniformMatrix4(_lampShader.UniformLocations["model"], true, ref lampMatrix); + GL.UniformMatrix4(_lampShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lampShader.UniformLocations["projection"], true, ref projection); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); diff --git a/Chapter2/3-Materials/Window.cs b/Chapter2/3-Materials/Window.cs index 987174f..797b12b 100644 --- a/Chapter2/3-Materials/Window.cs +++ b/Chapter2/3-Materials/Window.cs @@ -103,11 +103,11 @@ protected override void OnLoad() _vaoModel = GL.GenVertexArray(); GL.BindVertexArray(_vaoModel); - var positionLocation = _lightingShader.GetAttribLocation("aPos"); + var positionLocation = 0; // The location of aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), 0); - var normalLocation = _lightingShader.GetAttribLocation("aNormal"); + var normalLocation = 1; // The location of aNormal GL.EnableVertexAttribArray(normalLocation); GL.VertexAttribPointer(normalLocation, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), 3 * sizeof(float)); } @@ -116,7 +116,7 @@ protected override void OnLoad() _vaoLamp = GL.GenVertexArray(); GL.BindVertexArray(_vaoLamp); - var positionLocation = _lampShader.GetAttribLocation("aPos"); + var positionLocation = 0; // The location of aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), 0); } @@ -134,20 +134,24 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vaoModel); - _lightingShader.Use(); + GL.UseProgram(_lightingShader.Handle); - _lightingShader.SetMatrix4("model", Matrix4.Identity); - _lightingShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lightingShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + Matrix4 projection = _camera.GetProjectionMatrix(); + Matrix4 view = _camera.GetViewMatrix(); + Matrix4 model = Matrix4.Identity; - _lightingShader.SetVector3("viewPos", _camera.Position); + GL.UniformMatrix4(_lightingShader.UniformLocations["model"], true, ref model); + GL.UniformMatrix4(_lightingShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lightingShader.UniformLocations["projection"], true, ref projection); + + GL.Uniform3(_lightingShader.UniformLocations["viewPos"], _camera.Position); // Here we set the material values of the cube, the material struct is just a container so to access // the underlying values we simply type "material.value" to get the location of the uniform - _lightingShader.SetVector3("material.ambient", new Vector3(1.0f, 0.5f, 0.31f)); - _lightingShader.SetVector3("material.diffuse", new Vector3(1.0f, 0.5f, 0.31f)); - _lightingShader.SetVector3("material.specular", new Vector3(0.5f, 0.5f, 0.5f)); - _lightingShader.SetFloat("material.shininess", 32.0f); + GL.Uniform3(_lightingShader.UniformLocations["material.ambient"], new Vector3(1.0f, 0.5f, 0.31f)); + GL.Uniform3(_lightingShader.UniformLocations["material.diffuse"], new Vector3(1.0f, 0.5f, 0.31f)); + GL.Uniform3(_lightingShader.UniformLocations["material.specular"], new Vector3(1.0f, 0.5f, 0.5f)); + GL.Uniform1(_lightingShader.UniformLocations["material.shininess"], 32.0f); // This is where we change the lights color over time using the sin function Vector3 lightColor; @@ -160,24 +164,22 @@ protected override void OnRenderFrame(FrameEventArgs e) Vector3 ambientColor = lightColor * new Vector3(0.2f); Vector3 diffuseColor = lightColor * new Vector3(0.5f); - _lightingShader.SetVector3("light.position", _lightPos); - _lightingShader.SetVector3("light.ambient", ambientColor); - _lightingShader.SetVector3("light.diffuse", diffuseColor); - _lightingShader.SetVector3("light.specular", new Vector3(1.0f, 1.0f, 1.0f)); + GL.Uniform3(_lightingShader.UniformLocations["light.position"], _lightPos); + GL.Uniform3(_lightingShader.UniformLocations["light.ambient"], ambientColor); + GL.Uniform3(_lightingShader.UniformLocations["light.diffuse"], diffuseColor); + GL.Uniform3(_lightingShader.UniformLocations["light.specular"], new Vector3(1.0f, 1.0f, 1.0f)); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); GL.BindVertexArray(_vaoLamp); - _lampShader.Use(); + GL.UseProgram(_lampShader.Handle); - Matrix4 lampMatrix = Matrix4.Identity; - lampMatrix *= Matrix4.CreateScale(0.2f); - lampMatrix *= Matrix4.CreateTranslation(_lightPos); + Matrix4 lampMatrix = Matrix4.CreateScale(0.2f) * Matrix4.CreateTranslation(_lightPos); - _lampShader.SetMatrix4("model", lampMatrix); - _lampShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lampShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + GL.UniformMatrix4(_lampShader.UniformLocations["model"], true, ref lampMatrix); + GL.UniformMatrix4(_lampShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lampShader.UniformLocations["projection"], true, ref projection); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); diff --git a/Chapter2/4-LightingMaps/Shaders/lighting.frag b/Chapter2/4-LightingMaps/Shaders/lighting.frag index c7c21f0..e3f5be0 100644 --- a/Chapter2/4-LightingMaps/Shaders/lighting.frag +++ b/Chapter2/4-LightingMaps/Shaders/lighting.frag @@ -28,26 +28,26 @@ in vec3 FragPos; // Now we need the texture coordinates, however we only need one set even though we have 2 textures, // as every fragment should have the same texture position no matter what texture we are using. -in vec2 TexCoords; +in vec2 TexCoord; void main() { // Each of the 3 different components now use a texture for the material values instead of the object wide color they had before. // Note: The ambient and the diffuse share the same texture. // ambient - vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord)); // Diffuse vec3 norm = normalize(Normal); vec3 lightDir = normalize(light.position - FragPos); float diff = max(dot(norm, lightDir), 0.0); - vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoord)); // Specular vec3 viewDir = normalize(viewPos - FragPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord)); vec3 result = ambient + diffuse + specular; FragColor = vec4(result, 1.0); diff --git a/Chapter2/4-LightingMaps/Shaders/shader.vert b/Chapter2/4-LightingMaps/Shaders/shader.vert index af12da3..4fa340c 100644 --- a/Chapter2/4-LightingMaps/Shaders/shader.vert +++ b/Chapter2/4-LightingMaps/Shaders/shader.vert @@ -1,7 +1,7 @@ #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; -layout (location = 2) in vec2 aTexCoords; +layout (location = 2) in vec2 aTexCoord; uniform mat4 model; uniform mat4 view; @@ -9,12 +9,12 @@ uniform mat4 projection; out vec3 Normal; out vec3 FragPos; -out vec2 TexCoords; +out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 1.0) * model * view * projection; FragPos = vec3(vec4(aPos, 1.0) * model); Normal = aNormal * mat3(transpose(inverse(model))); - TexCoords = aTexCoords; + TexCoord = aTexCoord; } \ No newline at end of file diff --git a/Chapter2/4-LightingMaps/Window.cs b/Chapter2/4-LightingMaps/Window.cs index b3479b6..83068ec 100644 --- a/Chapter2/4-LightingMaps/Window.cs +++ b/Chapter2/4-LightingMaps/Window.cs @@ -4,6 +4,7 @@ using OpenTK.Windowing.Common; using OpenTK.Windowing.GraphicsLibraryFramework; using OpenTK.Windowing.Desktop; +using OpenTK.Graphics.GL; namespace LearnOpenTK { @@ -109,17 +110,17 @@ protected override void OnLoad() GL.BindVertexArray(_vaoModel); // All of the vertex attributes have been updated to now have a stride of 8 float sizes. - var positionLocation = _lightingShader.GetAttribLocation("aPos"); + var positionLocation = 0; // The location of aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0); - var normalLocation = _lightingShader.GetAttribLocation("aNormal"); + var normalLocation = 1; // The location of aNormal GL.EnableVertexAttribArray(normalLocation); GL.VertexAttribPointer(normalLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 3 * sizeof(float)); // The texture coords have now been added too, remember we only have 2 coordinates as the texture is 2d, // so the size parameter should only be 2 for the texture coordinates. - var texCoordLocation = _lightingShader.GetAttribLocation("aTexCoords"); + var texCoordLocation = 2; // The location of aTexCoord GL.EnableVertexAttribArray(texCoordLocation); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 8 * sizeof(float), 6 * sizeof(float)); } @@ -130,7 +131,7 @@ protected override void OnLoad() // The lamp shader should have its stride updated aswell, however we dont actually // use the texture coords for the lamp, so we dont need to add any extra attributes. - var positionLocation = _lampShader.GetAttribLocation("aPos"); + var positionLocation = 0; // The location of aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0); } @@ -157,38 +158,40 @@ protected override void OnRenderFrame(FrameEventArgs e) // and the specular map as our 1st texture. _diffuseMap.Use(TextureUnit.Texture0); _specularMap.Use(TextureUnit.Texture1); - _lightingShader.Use(); + GL.UseProgram(_lightingShader.Handle); - _lightingShader.SetMatrix4("model", Matrix4.Identity); - _lightingShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lightingShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + Matrix4 projection = _camera.GetProjectionMatrix(); + Matrix4 view = _camera.GetViewMatrix(); - _lightingShader.SetVector3("viewPos", _camera.Position); + Matrix4 model = Matrix4.Identity; - // Here we specify to the shaders what textures they should refer to when we want to get the positions. - _lightingShader.SetInt("material.diffuse", 0); - _lightingShader.SetInt("material.specular", 1); - _lightingShader.SetVector3("material.specular", new Vector3(0.5f, 0.5f, 0.5f)); - _lightingShader.SetFloat("material.shininess", 32.0f); + GL.UniformMatrix4(_lightingShader.UniformLocations["model"], true, ref model); + GL.UniformMatrix4(_lightingShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lightingShader.UniformLocations["projection"], true, ref projection); - _lightingShader.SetVector3("light.position", _lightPos); - _lightingShader.SetVector3("light.ambient", new Vector3(0.2f)); - _lightingShader.SetVector3("light.diffuse", new Vector3(0.5f)); - _lightingShader.SetVector3("light.specular", new Vector3(1.0f)); + GL.Uniform3(_lightingShader.UniformLocations["viewPos"], _camera.Position); + // Here we specify to the shaders what textures they should refer to when we want to get the positions. + GL.Uniform1(_lightingShader.UniformLocations["material.diffuse"], 0); + GL.Uniform1(_lightingShader.UniformLocations["material.specular"], 1); + GL.Uniform1(_lightingShader.UniformLocations["material.shininess"], 32.0f); + + GL.Uniform3(_lightingShader.UniformLocations["light.position"], _lightPos); + GL.Uniform3(_lightingShader.UniformLocations["light.ambient"], new Vector3(0.2f)); + GL.Uniform3(_lightingShader.UniformLocations["light.diffuse"], new Vector3(0.5f)); + GL.Uniform3(_lightingShader.UniformLocations["light.specular"], new Vector3(1.0f)); + GL.DrawArrays(PrimitiveType.Triangles, 0, 36); GL.BindVertexArray(_vaoLamp); - _lampShader.Use(); + GL.UseProgram(_lampShader.Handle); - Matrix4 lampMatrix = Matrix4.Identity; - lampMatrix *= Matrix4.CreateScale(0.2f); - lampMatrix *= Matrix4.CreateTranslation(_lightPos); + Matrix4 lampMatrix = Matrix4.CreateScale(0.2f) * Matrix4.CreateTranslation(_lightPos); - _lampShader.SetMatrix4("model", lampMatrix); - _lampShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lampShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + GL.UniformMatrix4(_lampShader.UniformLocations["model"], true, ref lampMatrix); + GL.UniformMatrix4(_lampShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lampShader.UniformLocations["projection"], true, ref projection); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); diff --git a/Chapter2/5-LightCasters-DirectionalLights/5-LightCasters-DirectionalLights.csproj b/Chapter2/5-LightCasters-DirectionalLights/5-LightCasters-DirectionalLights.csproj index 182a118..20342b8 100644 --- a/Chapter2/5-LightCasters-DirectionalLights/5-LightCasters-DirectionalLights.csproj +++ b/Chapter2/5-LightCasters-DirectionalLights/5-LightCasters-DirectionalLights.csproj @@ -18,4 +18,16 @@ + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + \ No newline at end of file diff --git a/Chapter2/5-LightCasters-DirectionalLights/Shaders/lighting.frag b/Chapter2/5-LightCasters-DirectionalLights/Shaders/lighting.frag index d2cb8bf..2480cab 100644 --- a/Chapter2/5-LightCasters-DirectionalLights/Shaders/lighting.frag +++ b/Chapter2/5-LightCasters-DirectionalLights/Shaders/lighting.frag @@ -21,25 +21,25 @@ uniform vec3 viewPos; out vec4 FragColor; in vec3 Normal; -in vec2 TexCoords; +in vec2 TexCoord; void main() { // ambient - vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord)); // diffuse vec3 norm = normalize(Normal); vec3 lightDir = normalize(-light.direction);//We still normalize the light direction since we techically dont know, //wether it was normalized for us or not. float diff = max(dot(norm, lightDir), 0.0); - vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoord)); // specular vec3 viewDir = normalize(viewPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord)); vec3 result = ambient + diffuse + specular; FragColor = vec4(result, 1.0); diff --git a/Chapter2/5-LightCasters-DirectionalLights/Shaders/shader.vert b/Chapter2/5-LightCasters-DirectionalLights/Shaders/shader.vert index 5604e7b..9a0c35f 100644 --- a/Chapter2/5-LightCasters-DirectionalLights/Shaders/shader.vert +++ b/Chapter2/5-LightCasters-DirectionalLights/Shaders/shader.vert @@ -1,18 +1,18 @@ #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; -layout (location = 2) in vec2 aTexCoords; +layout (location = 2) in vec2 aTexCoord; uniform mat4 model; uniform mat4 view; uniform mat4 projection; out vec3 Normal; -out vec2 TexCoords; +out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 1.0) * model * view * projection; Normal = aNormal * mat3(transpose(inverse(model))); - TexCoords = aTexCoords; + TexCoord = aTexCoord; } \ No newline at end of file diff --git a/Chapter2/5-LightCasters-DirectionalLights/Window.cs b/Chapter2/5-LightCasters-DirectionalLights/Window.cs index 9a75fc0..58c2c22 100644 --- a/Chapter2/5-LightCasters-DirectionalLights/Window.cs +++ b/Chapter2/5-LightCasters-DirectionalLights/Window.cs @@ -4,6 +4,7 @@ using OpenTK.Windowing.Common; using OpenTK.Windowing.GraphicsLibraryFramework; using OpenTK.Windowing.Desktop; +using System.Reflection; namespace LearnOpenTK { @@ -120,15 +121,15 @@ protected override void OnLoad() _vaoModel = GL.GenVertexArray(); GL.BindVertexArray(_vaoModel); - var positionLocation = _lightingShader.GetAttribLocation("aPos"); + var positionLocation = 0; // aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0); - var normalLocation = _lightingShader.GetAttribLocation("aNormal"); + var normalLocation = 1; // aNormal GL.EnableVertexAttribArray(normalLocation); GL.VertexAttribPointer(normalLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 3 * sizeof(float)); - var texCoordLocation = _lightingShader.GetAttribLocation("aTexCoords"); + var texCoordLocation = 2; // aTexCoord GL.EnableVertexAttribArray(texCoordLocation); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 8 * sizeof(float), 6 * sizeof(float)); } @@ -139,7 +140,7 @@ protected override void OnLoad() GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject); - var positionLocation = _lampShader.GetAttribLocation("aPos"); + var positionLocation = 0; // aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0); } @@ -162,23 +163,26 @@ protected override void OnRenderFrame(FrameEventArgs e) _diffuseMap.Use(TextureUnit.Texture0); _specularMap.Use(TextureUnit.Texture1); - _lightingShader.Use(); + GL.UseProgram(_lightingShader.Handle); - _lightingShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lightingShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + Matrix4 projection = _camera.GetProjectionMatrix(); + Matrix4 view = _camera.GetViewMatrix(); - _lightingShader.SetVector3("viewPos", _camera.Position); + GL.UniformMatrix4(_lightingShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lightingShader.UniformLocations["projection"], true, ref projection); - _lightingShader.SetInt("material.diffuse", 0); - _lightingShader.SetInt("material.specular", 1); - _lightingShader.SetVector3("material.specular", new Vector3(0.5f, 0.5f, 0.5f)); - _lightingShader.SetFloat("material.shininess", 32.0f); + GL.Uniform3(_lightingShader.UniformLocations["viewPos"], _camera.Position); + + // Here we specify to the shaders what textures they should refer to when we want to get the positions. + GL.Uniform1(_lightingShader.UniformLocations["material.diffuse"], 0); + GL.Uniform1(_lightingShader.UniformLocations["material.specular"], 1); + GL.Uniform1(_lightingShader.UniformLocations["material.shininess"], 32.0f); // Directional light needs a direction, in this example we just use (-0.2, -1.0, -0.3f) as the lights direction - _lightingShader.SetVector3("light.direction", new Vector3(-0.2f, -1.0f, -0.3f)); - _lightingShader.SetVector3("light.ambient", new Vector3(0.2f)); - _lightingShader.SetVector3("light.diffuse", new Vector3(0.5f)); - _lightingShader.SetVector3("light.specular", new Vector3(1.0f)); + GL.Uniform3(_lightingShader.UniformLocations["light.direction"], new Vector3(-0.2f, -1.0f, -0.3f)); + GL.Uniform3(_lightingShader.UniformLocations["light.ambient"], new Vector3(0.2f)); + GL.Uniform3(_lightingShader.UniformLocations["light.diffuse"], new Vector3(0.5f)); + GL.Uniform3(_lightingShader.UniformLocations["light.specular"], new Vector3(1.0f)); // We want to draw all the cubes at their respective positions for (int i = 0; i < _cubePositions.Length; i++) @@ -188,8 +192,8 @@ protected override void OnRenderFrame(FrameEventArgs e) // We then calculate the angle and rotate the model around an axis float angle = 20.0f * i; model = model * Matrix4.CreateFromAxisAngle(new Vector3(1.0f, 0.3f, 0.5f), angle); - // Remember to set the model at last so it can be used by opentk - _lightingShader.SetMatrix4("model", model); + // Remember to set the model at last so it can be used by opengl + GL.UniformMatrix4(_lightingShader.UniformLocations["model"], true, ref model); // At last we draw all our cubes GL.DrawArrays(PrimitiveType.Triangles, 0, 36); @@ -197,14 +201,13 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vaoLamp); - _lampShader.Use(); + GL.UseProgram(_lampShader.Handle); - Matrix4 lampMatrix = Matrix4.CreateScale(0.2f); - lampMatrix = lampMatrix * Matrix4.CreateTranslation(_lightPos); + Matrix4 lampMatrix = Matrix4.CreateScale(0.2f) * Matrix4.CreateTranslation(_lightPos); - _lampShader.SetMatrix4("model", lampMatrix); - _lampShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lampShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + GL.UniformMatrix4(_lampShader.UniformLocations["model"], true, ref lampMatrix); + GL.UniformMatrix4(_lampShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lampShader.UniformLocations["projection"], true, ref projection); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); diff --git a/Chapter2/5-LightCasters-PointLights/5-LightCasters-PointLights.csproj b/Chapter2/5-LightCasters-PointLights/5-LightCasters-PointLights.csproj index 182a118..20342b8 100644 --- a/Chapter2/5-LightCasters-PointLights/5-LightCasters-PointLights.csproj +++ b/Chapter2/5-LightCasters-PointLights/5-LightCasters-PointLights.csproj @@ -18,4 +18,16 @@ + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + \ No newline at end of file diff --git a/Chapter2/5-LightCasters-PointLights/Shaders/lighting.frag b/Chapter2/5-LightCasters-PointLights/Shaders/lighting.frag index a32b305..e7975a2 100644 --- a/Chapter2/5-LightCasters-PointLights/Shaders/lighting.frag +++ b/Chapter2/5-LightCasters-PointLights/Shaders/lighting.frag @@ -28,25 +28,25 @@ out vec4 FragColor; in vec3 Normal; in vec3 FragPos; -in vec2 TexCoords; +in vec2 TexCoord; void main() { //ambient - vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord)); //diffuse vec3 norm = normalize(Normal); vec3 lightDir = normalize(light.position - FragPos); float diff = max(dot(norm, lightDir), 0.0); - vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoord)); //specular vec3 viewDir = normalize(viewPos - FragPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord)); //attenuation //The attenuation is the term we use when talking about how dim the light gets over distance diff --git a/Chapter2/5-LightCasters-PointLights/Shaders/shader.vert b/Chapter2/5-LightCasters-PointLights/Shaders/shader.vert index af12da3..4fa340c 100644 --- a/Chapter2/5-LightCasters-PointLights/Shaders/shader.vert +++ b/Chapter2/5-LightCasters-PointLights/Shaders/shader.vert @@ -1,7 +1,7 @@ #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; -layout (location = 2) in vec2 aTexCoords; +layout (location = 2) in vec2 aTexCoord; uniform mat4 model; uniform mat4 view; @@ -9,12 +9,12 @@ uniform mat4 projection; out vec3 Normal; out vec3 FragPos; -out vec2 TexCoords; +out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 1.0) * model * view * projection; FragPos = vec3(vec4(aPos, 1.0) * model); Normal = aNormal * mat3(transpose(inverse(model))); - TexCoords = aTexCoords; + TexCoord = aTexCoord; } \ No newline at end of file diff --git a/Chapter2/5-LightCasters-PointLights/Window.cs b/Chapter2/5-LightCasters-PointLights/Window.cs index a40b7ea..ed09816 100644 --- a/Chapter2/5-LightCasters-PointLights/Window.cs +++ b/Chapter2/5-LightCasters-PointLights/Window.cs @@ -121,15 +121,15 @@ protected override void OnLoad() _vaoModel = GL.GenVertexArray(); GL.BindVertexArray(_vaoModel); - var positionLocation = _lightingShader.GetAttribLocation("aPos"); + var positionLocation = 0; // aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0); - var normalLocation = _lightingShader.GetAttribLocation("aNormal"); + var normalLocation = 1; // aNormal GL.EnableVertexAttribArray(normalLocation); GL.VertexAttribPointer(normalLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 3 * sizeof(float)); - var texCoordLocation = _lightingShader.GetAttribLocation("aTexCoords"); + var texCoordLocation = 2; // aTexCoord GL.EnableVertexAttribArray(texCoordLocation); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 8 * sizeof(float), 6 * sizeof(float)); } @@ -138,7 +138,7 @@ protected override void OnLoad() _vaoLamp = GL.GenVertexArray(); GL.BindVertexArray(_vaoLamp); - var positionLocation = _lampShader.GetAttribLocation("aPos"); + var positionLocation = 0; // aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0); } @@ -161,25 +161,29 @@ protected override void OnRenderFrame(FrameEventArgs e) _diffuseMap.Use(TextureUnit.Texture0); _specularMap.Use(TextureUnit.Texture1); - _lightingShader.Use(); + GL.UseProgram(_lightingShader.Handle); - _lightingShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lightingShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + Matrix4 projection = _camera.GetProjectionMatrix(); + Matrix4 view = _camera.GetViewMatrix(); - _lightingShader.SetVector3("viewPos", _camera.Position); + GL.UniformMatrix4(_lightingShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lightingShader.UniformLocations["projection"], true, ref projection); - _lightingShader.SetInt("material.diffuse", 0); - _lightingShader.SetInt("material.specular", 1); - _lightingShader.SetVector3("material.specular", new Vector3(0.5f, 0.5f, 0.5f)); - _lightingShader.SetFloat("material.shininess", 32.0f); + GL.Uniform3(_lightingShader.UniformLocations["viewPos"], _camera.Position); - _lightingShader.SetVector3("light.position", _lightPos); - _lightingShader.SetFloat("light.constant", 1.0f); - _lightingShader.SetFloat("light.linear", 0.09f); - _lightingShader.SetFloat("light.quadratic", 0.032f); - _lightingShader.SetVector3("light.ambient", new Vector3(0.2f)); - _lightingShader.SetVector3("light.diffuse", new Vector3(0.5f)); - _lightingShader.SetVector3("light.specular", new Vector3(1.0f)); + // Here we specify to the shaders what textures they should refer to when we want to get the positions. + GL.Uniform1(_lightingShader.UniformLocations["material.diffuse"], 0); + GL.Uniform1(_lightingShader.UniformLocations["material.specular"], 1); + GL.Uniform1(_lightingShader.UniformLocations["material.shininess"], 32.0f); + + // Directional light needs a direction, in this example we just use (-0.2, -1.0, -0.3f) as the lights direction + GL.Uniform3(_lightingShader.UniformLocations["light.position"], _lightPos); + GL.Uniform1(_lightingShader.UniformLocations["light.constant"], 1.0f); + GL.Uniform1(_lightingShader.UniformLocations["light.linear"], 0.09f); + GL.Uniform1(_lightingShader.UniformLocations["light.quadratic"], 0.032f); + GL.Uniform3(_lightingShader.UniformLocations["light.ambient"], new Vector3(0.2f)); + GL.Uniform3(_lightingShader.UniformLocations["light.diffuse"], new Vector3(0.5f)); + GL.Uniform3(_lightingShader.UniformLocations["light.specular"], new Vector3(1.0f)); // We want to draw all the cubes at their respective positions for (int i = 0; i < _cubePositions.Length; i++) @@ -191,7 +195,7 @@ protected override void OnRenderFrame(FrameEventArgs e) float angle = 20.0f * i; model = model * Matrix4.CreateFromAxisAngle(new Vector3(1.0f, 0.3f, 0.5f), angle); // Remember to set the model at last so it can be used by opentk - _lightingShader.SetMatrix4("model", model); + GL.UniformMatrix4(_lightingShader.UniformLocations["model"], true, ref model); // At last we draw all our cubes GL.DrawArrays(PrimitiveType.Triangles, 0, 36); @@ -199,14 +203,13 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vaoLamp); - _lampShader.Use(); + GL.UseProgram(_lampShader.Handle); - Matrix4 lampMatrix = Matrix4.CreateScale(0.2f); - lampMatrix = lampMatrix * Matrix4.CreateTranslation(_lightPos); + Matrix4 lampMatrix = Matrix4.CreateScale(0.2f) * Matrix4.CreateTranslation(_lightPos); - _lampShader.SetMatrix4("model", lampMatrix); - _lampShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lampShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + GL.UniformMatrix4(_lampShader.UniformLocations["model"], true, ref lampMatrix); + GL.UniformMatrix4(_lampShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lampShader.UniformLocations["projection"], true, ref projection); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); diff --git a/Chapter2/5-LightCasters-Spotlight/Shaders/lighting.frag b/Chapter2/5-LightCasters-Spotlight/Shaders/lighting.frag index 78abfaf..a421a32 100644 --- a/Chapter2/5-LightCasters-Spotlight/Shaders/lighting.frag +++ b/Chapter2/5-LightCasters-Spotlight/Shaders/lighting.frag @@ -29,24 +29,24 @@ out vec4 FragColor; in vec3 Normal; in vec3 FragPos; -in vec2 TexCoords; +in vec2 TexCoord; void main() { //ambient - vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord)); //diffuse vec3 norm = normalize(Normal); vec3 lightDir = normalize(light.position - FragPos); float diff = max(dot(norm, lightDir), 0.0); - vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoord)); //specular vec3 viewDir = normalize(viewPos - FragPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord)); //attenuation float distance = length(light.position - FragPos); diff --git a/Chapter2/5-LightCasters-Spotlight/Shaders/shader.vert b/Chapter2/5-LightCasters-Spotlight/Shaders/shader.vert index af12da3..4fa340c 100644 --- a/Chapter2/5-LightCasters-Spotlight/Shaders/shader.vert +++ b/Chapter2/5-LightCasters-Spotlight/Shaders/shader.vert @@ -1,7 +1,7 @@ #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; -layout (location = 2) in vec2 aTexCoords; +layout (location = 2) in vec2 aTexCoord; uniform mat4 model; uniform mat4 view; @@ -9,12 +9,12 @@ uniform mat4 projection; out vec3 Normal; out vec3 FragPos; -out vec2 TexCoords; +out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 1.0) * model * view * projection; FragPos = vec3(vec4(aPos, 1.0) * model); Normal = aNormal * mat3(transpose(inverse(model))); - TexCoords = aTexCoords; + TexCoord = aTexCoord; } \ No newline at end of file diff --git a/Chapter2/5-LightCasters-Spotlight/Window.cs b/Chapter2/5-LightCasters-Spotlight/Window.cs index 792373c..29ce501 100644 --- a/Chapter2/5-LightCasters-Spotlight/Window.cs +++ b/Chapter2/5-LightCasters-Spotlight/Window.cs @@ -123,15 +123,15 @@ protected override void OnLoad() _vaoModel = GL.GenVertexArray(); GL.BindVertexArray(_vaoModel); - var positionLocation = _lightingShader.GetAttribLocation("aPos"); + var positionLocation = 0; // aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0); - var normalLocation = _lightingShader.GetAttribLocation("aNormal"); + var normalLocation = 1; // aNormal GL.EnableVertexAttribArray(normalLocation); GL.VertexAttribPointer(normalLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 3 * sizeof(float)); - var texCoordLocation = _lightingShader.GetAttribLocation("aTexCoords"); + var texCoordLocation = 2; // aTexCoord GL.EnableVertexAttribArray(texCoordLocation); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 8 * sizeof(float), 6 * sizeof(float)); } @@ -140,7 +140,7 @@ protected override void OnLoad() _vaoLamp = GL.GenVertexArray(); GL.BindVertexArray(_vaoLamp); - var positionLocation = _lampShader.GetAttribLocation("aPos"); + var positionLocation = 0; // aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0); } @@ -163,28 +163,32 @@ protected override void OnRenderFrame(FrameEventArgs e) _diffuseMap.Use(TextureUnit.Texture0); _specularMap.Use(TextureUnit.Texture1); - _lightingShader.Use(); + GL.UseProgram(_lightingShader.Handle); - _lightingShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lightingShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + Matrix4 projection = _camera.GetProjectionMatrix(); + Matrix4 view = _camera.GetViewMatrix(); - _lightingShader.SetVector3("viewPos", _camera.Position); + GL.UniformMatrix4(_lightingShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lightingShader.UniformLocations["projection"], true, ref projection); - _lightingShader.SetInt("material.diffuse", 0); - _lightingShader.SetInt("material.specular", 1); - _lightingShader.SetVector3("material.specular", new Vector3(0.5f, 0.5f, 0.5f)); - _lightingShader.SetFloat("material.shininess", 32.0f); + GL.Uniform3(_lightingShader.UniformLocations["viewPos"], _camera.Position); - _lightingShader.SetVector3("light.position", _camera.Position); - _lightingShader.SetVector3("light.direction", _camera.Front); - _lightingShader.SetFloat("light.cutOff", MathF.Cos(MathHelper.DegreesToRadians(12.5f))); - _lightingShader.SetFloat("light.outerCutOff", MathF.Cos(MathHelper.DegreesToRadians(17.5f))); - _lightingShader.SetFloat("light.constant", 1.0f); - _lightingShader.SetFloat("light.linear", 0.09f); - _lightingShader.SetFloat("light.quadratic", 0.032f); - _lightingShader.SetVector3("light.ambient", new Vector3(0.2f)); - _lightingShader.SetVector3("light.diffuse", new Vector3(0.5f)); - _lightingShader.SetVector3("light.specular", new Vector3(1.0f)); + // Here we specify to the shaders what textures they should refer to when we want to get the positions. + GL.Uniform1(_lightingShader.UniformLocations["material.diffuse"], 0); + GL.Uniform1(_lightingShader.UniformLocations["material.specular"], 1); + GL.Uniform1(_lightingShader.UniformLocations["material.shininess"], 32.0f); + + // Directional light needs a direction, in this example we just use (-0.2, -1.0, -0.3f) as the lights direction + GL.Uniform3(_lightingShader.UniformLocations["light.position"], _camera.Position); + GL.Uniform3(_lightingShader.UniformLocations["light.direction"], _camera.Front); + GL.Uniform1(_lightingShader.UniformLocations["light.cutOff"], MathF.Cos(MathHelper.DegreesToRadians(12.5f))); + GL.Uniform1(_lightingShader.UniformLocations["light.outerCutOff"], MathF.Cos(MathHelper.DegreesToRadians(17.5f))); + GL.Uniform1(_lightingShader.UniformLocations["light.constant"], 1.0f); + GL.Uniform1(_lightingShader.UniformLocations["light.linear"], 0.09f); + GL.Uniform1(_lightingShader.UniformLocations["light.quadratic"], 0.032f); + GL.Uniform3(_lightingShader.UniformLocations["light.ambient"], new Vector3(0.2f)); + GL.Uniform3(_lightingShader.UniformLocations["light.diffuse"], new Vector3(0.5f)); + GL.Uniform3(_lightingShader.UniformLocations["light.specular"], new Vector3(1.0f)); // We want to draw all the cubes at their respective positions for (int i = 0; i < _cubePositions.Length; i++) @@ -195,7 +199,7 @@ protected override void OnRenderFrame(FrameEventArgs e) float angle = 20.0f * i; model = model * Matrix4.CreateFromAxisAngle(new Vector3(1.0f, 0.3f, 0.5f), angle); // Remember to set the model at last so it can be used by opentk - _lightingShader.SetMatrix4("model", model); + GL.UniformMatrix4(_lightingShader.UniformLocations["model"], true, ref model); // At last we draw all our cubes GL.DrawArrays(PrimitiveType.Triangles, 0, 36); @@ -203,14 +207,13 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vaoLamp); - _lampShader.Use(); + GL.UseProgram(_lampShader.Handle); - Matrix4 lampMatrix = Matrix4.CreateScale(0.2f); - lampMatrix = lampMatrix * Matrix4.CreateTranslation(_lightPos); + Matrix4 lampMatrix = Matrix4.CreateScale(0.2f) * Matrix4.CreateTranslation(_lightPos); - _lampShader.SetMatrix4("model", lampMatrix); - _lampShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lampShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + GL.UniformMatrix4(_lampShader.UniformLocations["model"], true, ref lampMatrix); + GL.UniformMatrix4(_lampShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lampShader.UniformLocations["projection"], true, ref projection); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); diff --git a/Chapter2/6-MultipleLights/Shaders/lighting.frag b/Chapter2/6-MultipleLights/Shaders/lighting.frag index b68142b..5746618 100644 --- a/Chapter2/6-MultipleLights/Shaders/lighting.frag +++ b/Chapter2/6-MultipleLights/Shaders/lighting.frag @@ -54,7 +54,7 @@ out vec4 FragColor; in vec3 Normal; in vec3 FragPos; -in vec2 TexCoords; +in vec2 TexCoord; //Here we have some function prototypes, these are the signatures the gpu will use to know how the //parameters of each light calculation is layed out. @@ -89,9 +89,9 @@ vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir) vec3 reflectDir = reflect(-lightDir, normal); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); //combine results - vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); - vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); - vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoord)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord)); return (ambient + diffuse + specular); } @@ -108,9 +108,9 @@ vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); //combine results - vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); - vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); - vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoord)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord)); ambient *= attenuation; diffuse *= attenuation; specular *= attenuation; @@ -138,9 +138,9 @@ vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir) float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); //combine results - vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); - vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); - vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoord)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord)); ambient *= attenuation; diffuse *= attenuation * intensity; specular *= attenuation * intensity; diff --git a/Chapter2/6-MultipleLights/Shaders/shader.vert b/Chapter2/6-MultipleLights/Shaders/shader.vert index af12da3..4fa340c 100644 --- a/Chapter2/6-MultipleLights/Shaders/shader.vert +++ b/Chapter2/6-MultipleLights/Shaders/shader.vert @@ -1,7 +1,7 @@ #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; -layout (location = 2) in vec2 aTexCoords; +layout (location = 2) in vec2 aTexCoord; uniform mat4 model; uniform mat4 view; @@ -9,12 +9,12 @@ uniform mat4 projection; out vec3 Normal; out vec3 FragPos; -out vec2 TexCoords; +out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 1.0) * model * view * projection; FragPos = vec3(vec4(aPos, 1.0) * model); Normal = aNormal * mat3(transpose(inverse(model))); - TexCoords = aTexCoords; + TexCoord = aTexCoord; } \ No newline at end of file diff --git a/Chapter2/6-MultipleLights/Window.cs b/Chapter2/6-MultipleLights/Window.cs index 4b64d2c..2101691 100644 --- a/Chapter2/6-MultipleLights/Window.cs +++ b/Chapter2/6-MultipleLights/Window.cs @@ -125,15 +125,15 @@ protected override void OnLoad() _vaoModel = GL.GenVertexArray(); GL.BindVertexArray(_vaoModel); - var positionLocation = _lightingShader.GetAttribLocation("aPos"); + var positionLocation = 0; // aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0); - var normalLocation = _lightingShader.GetAttribLocation("aNormal"); + var normalLocation = 1; // aNormal GL.EnableVertexAttribArray(normalLocation); GL.VertexAttribPointer(normalLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 3 * sizeof(float)); - var texCoordLocation = _lightingShader.GetAttribLocation("aTexCoords"); + var texCoordLocation = 2; // aTexCoord GL.EnableVertexAttribArray(texCoordLocation); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 8 * sizeof(float), 6 * sizeof(float)); } @@ -142,7 +142,7 @@ protected override void OnLoad() _vaoLamp = GL.GenVertexArray(); GL.BindVertexArray(_vaoLamp); - var positionLocation = _lampShader.GetAttribLocation("aPos"); + var positionLocation = 0; // aPos GL.EnableVertexAttribArray(positionLocation); GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0); } @@ -165,17 +165,19 @@ protected override void OnRenderFrame(FrameEventArgs e) _diffuseMap.Use(TextureUnit.Texture0); _specularMap.Use(TextureUnit.Texture1); - _lightingShader.Use(); + GL.UseProgram(_lightingShader.Handle); - _lightingShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lightingShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + Matrix4 projection = _camera.GetProjectionMatrix(); + Matrix4 view = _camera.GetViewMatrix(); - _lightingShader.SetVector3("viewPos", _camera.Position); + GL.UniformMatrix4(_lightingShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lightingShader.UniformLocations["projection"], true, ref projection); - _lightingShader.SetInt("material.diffuse", 0); - _lightingShader.SetInt("material.specular", 1); - _lightingShader.SetVector3("material.specular", new Vector3(0.5f, 0.5f, 0.5f)); - _lightingShader.SetFloat("material.shininess", 32.0f); + GL.Uniform3(_lightingShader.UniformLocations["viewPos"], _camera.Position); + + GL.Uniform1(_lightingShader.UniformLocations["material.diffuse"], 0); + GL.Uniform1(_lightingShader.UniformLocations["material.specular"], 1); + GL.Uniform1(_lightingShader.UniformLocations["material.shininess"], 32.0f); /* Here we set all the uniforms for the 5/6 types of lights we have. We have to set them manually and index @@ -184,58 +186,57 @@ protected override void OnRenderFrame(FrameEventArgs e) by using 'Uniform buffer objects', but that is something we'll discuss in the 'Advanced GLSL' tutorial. */ // Directional light - _lightingShader.SetVector3("dirLight.direction", new Vector3(-0.2f, -1.0f, -0.3f)); - _lightingShader.SetVector3("dirLight.ambient", new Vector3(0.05f, 0.05f, 0.05f)); - _lightingShader.SetVector3("dirLight.diffuse", new Vector3(0.4f, 0.4f, 0.4f)); - _lightingShader.SetVector3("dirLight.specular", new Vector3(0.5f, 0.5f, 0.5f)); + GL.Uniform3(_lightingShader.UniformLocations["dirLight.direction"], new Vector3(-0.2f, -1.0f, -0.3f)); + GL.Uniform3(_lightingShader.UniformLocations["dirLight.ambient"], new Vector3(0.05f, 0.05f, 0.05f)); + GL.Uniform3(_lightingShader.UniformLocations["dirLight.diffuse"], new Vector3(0.4f, 0.4f, 0.4f)); + GL.Uniform3(_lightingShader.UniformLocations["dirLight.specular"], new Vector3(0.5f, 0.5f, 0.5f)); // Point lights for (int i = 0; i < _pointLightPositions.Length; i++) { - _lightingShader.SetVector3($"pointLights[{i}].position", _pointLightPositions[i]); - _lightingShader.SetVector3($"pointLights[{i}].ambient", new Vector3(0.05f, 0.05f, 0.05f)); - _lightingShader.SetVector3($"pointLights[{i}].diffuse", new Vector3(0.8f, 0.8f, 0.8f)); - _lightingShader.SetVector3($"pointLights[{i}].specular", new Vector3(1.0f, 1.0f, 1.0f)); - _lightingShader.SetFloat($"pointLights[{i}].constant", 1.0f); - _lightingShader.SetFloat($"pointLights[{i}].linear", 0.09f); - _lightingShader.SetFloat($"pointLights[{i}].quadratic", 0.032f); + GL.Uniform3(_lightingShader.UniformLocations[$"pointLights[{i}].position"], _pointLightPositions[i]); + GL.Uniform3(_lightingShader.UniformLocations[$"pointLights[{i}].ambient"], new Vector3(0.05f, 0.05f, 0.05f)); + GL.Uniform3(_lightingShader.UniformLocations[$"pointLights[{i}].diffuse"], new Vector3(0.8f, 0.8f, 0.8f)); + GL.Uniform3(_lightingShader.UniformLocations[$"pointLights[{i}].specular"], new Vector3(1.0f, 1.0f, 1.0f)); + GL.Uniform1(_lightingShader.UniformLocations[$"pointLights[{i}].constant"], 1.0f); + GL.Uniform1(_lightingShader.UniformLocations[$"pointLights[{i}].linear"], 0.09f); + GL.Uniform1(_lightingShader.UniformLocations[$"pointLights[{i}].quadratic"], 0.032f); } // Spot light - _lightingShader.SetVector3("spotLight.position", _camera.Position); - _lightingShader.SetVector3("spotLight.direction", _camera.Front); - _lightingShader.SetVector3("spotLight.ambient", new Vector3(0.0f, 0.0f, 0.0f)); - _lightingShader.SetVector3("spotLight.diffuse", new Vector3(1.0f, 1.0f, 1.0f)); - _lightingShader.SetVector3("spotLight.specular", new Vector3(1.0f, 1.0f, 1.0f)); - _lightingShader.SetFloat("spotLight.constant", 1.0f); - _lightingShader.SetFloat("spotLight.linear", 0.09f); - _lightingShader.SetFloat("spotLight.quadratic", 0.032f); - _lightingShader.SetFloat("spotLight.cutOff", MathF.Cos(MathHelper.DegreesToRadians(12.5f))); - _lightingShader.SetFloat("spotLight.outerCutOff", MathF.Cos(MathHelper.DegreesToRadians(17.5f))); + GL.Uniform3(_lightingShader.UniformLocations["spotLight.position"], _camera.Position); + GL.Uniform3(_lightingShader.UniformLocations["spotLight.direction"], _camera.Front); + GL.Uniform3(_lightingShader.UniformLocations["spotLight.ambient"], new Vector3(0.0f, 0.0f, 0.0f)); + GL.Uniform3(_lightingShader.UniformLocations["spotLight.diffuse"], new Vector3(1.0f, 1.0f, 1.0f)); + GL.Uniform3(_lightingShader.UniformLocations["spotLight.specular"], new Vector3(1.0f, 1.0f, 1.0f)); + GL.Uniform1(_lightingShader.UniformLocations["spotLight.constant"], 1.0f); + GL.Uniform1(_lightingShader.UniformLocations["spotLight.linear"], 0.09f); + GL.Uniform1(_lightingShader.UniformLocations["spotLight.quadratic"], 0.032f); + GL.Uniform1(_lightingShader.UniformLocations["spotLight.cutOff"], MathF.Cos(MathHelper.DegreesToRadians(12.5f))); + GL.Uniform1(_lightingShader.UniformLocations["spotLight.outerCutOff"], MathF.Cos(MathHelper.DegreesToRadians(17.5f))); for (int i = 0; i < _cubePositions.Length; i++) { Matrix4 model = Matrix4.CreateTranslation(_cubePositions[i]); float angle = 20.0f * i; model = model * Matrix4.CreateFromAxisAngle(new Vector3(1.0f, 0.3f, 0.5f), angle); - _lightingShader.SetMatrix4("model", model); + GL.UniformMatrix4(_lightingShader.UniformLocations["model"], true, ref model); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); } GL.BindVertexArray(_vaoLamp); - _lampShader.Use(); + GL.UseProgram(_lampShader.Handle); - _lampShader.SetMatrix4("view", _camera.GetViewMatrix()); - _lampShader.SetMatrix4("projection", _camera.GetProjectionMatrix()); + GL.UniformMatrix4(_lampShader.UniformLocations["view"], true, ref view); + GL.UniformMatrix4(_lampShader.UniformLocations["projection"], true, ref projection); // We use a loop to draw all the lights at the proper position for (int i = 0; i < _pointLightPositions.Length; i++) { - Matrix4 lampMatrix = Matrix4.CreateScale(0.2f); - lampMatrix = lampMatrix * Matrix4.CreateTranslation(_pointLightPositions[i]); + Matrix4 lampMatrix = Matrix4.CreateScale(0.2f) * Matrix4.CreateTranslation(_pointLightPositions[i]); - _lampShader.SetMatrix4("model", lampMatrix); + GL.UniformMatrix4(_lampShader.UniformLocations["model"], true, ref lampMatrix); GL.DrawArrays(PrimitiveType.Triangles, 0, 36); } diff --git a/Common/Shader.cs b/Common/Shader.cs index b1e6b8b..2e0a66c 100644 --- a/Common/Shader.cs +++ b/Common/Shader.cs @@ -4,21 +4,40 @@ using System.Collections.Generic; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; +using System.Reflection.Metadata; +using System.ComponentModel; namespace LearnOpenTK.Common { - // A simple class meant to help create shaders. - public class Shader + public static class ShaderUtils { - public readonly int Handle; + // This function creates a dictionary that maps uniform names to their location, + // this is used to speed up uniform location queries. + public static Dictionary CreateUniformLocationsDict(int program) + { + // First, we have to get the number of active uniforms in the shader. + GL.GetProgram(program, GetProgramParameterName.ActiveUniforms, out var numberOfUniforms); + + // Next, allocate the dictionary to hold the locations. + Dictionary uniformLocations = new Dictionary(); - private readonly Dictionary _uniformLocations; + // Loop over all the uniforms, + for (var i = 0; i < numberOfUniforms; i++) + { + // get the name of this uniform, + var key = GL.GetActiveUniform(program, i, out _, out _); + + // get the location, + var location = GL.GetUniformLocation(program, key); - // This is how you create a simple shader. - // Shaders are written in GLSL, which is a language very similar to C in its semantics. - // The GLSL source is compiled *at runtime*, so it can optimize itself for the graphics card it's currently being used on. - // A commented example of GLSL can be found in shader.vert. - public Shader(string vertPath, string fragPath) + // and then add it to the dictionary. + uniformLocations.Add(key, location); + } + + return uniformLocations; + } + + public static int Compile(string vertexPath, string fragmentPath) { // There are several different types of shaders, but the only two you need for basic rendering are the vertex and fragment shaders. // The vertex shader is responsible for moving around vertices, and uploading that data to the fragment shader. @@ -27,7 +46,7 @@ public Shader(string vertPath, string fragPath) // The fragment shader is what we'll be using the most here. // Load vertex shader and compile - var shaderSource = File.ReadAllText(vertPath); + var shaderSource = File.ReadAllText(vertexPath); // GL.CreateShader will create an empty shader (obviously). The ShaderType enum denotes which type of shader will be created. var vertexShader = GL.CreateShader(ShaderType.VertexShader); @@ -39,51 +58,30 @@ public Shader(string vertPath, string fragPath) CompileShader(vertexShader); // We do the same for the fragment shader. - shaderSource = File.ReadAllText(fragPath); + shaderSource = File.ReadAllText(fragmentPath); var fragmentShader = GL.CreateShader(ShaderType.FragmentShader); GL.ShaderSource(fragmentShader, shaderSource); CompileShader(fragmentShader); // These two shaders must then be merged into a shader program, which can then be used by OpenGL. // To do this, create a program... - Handle = GL.CreateProgram(); + int handle = GL.CreateProgram(); // Attach both shaders... - GL.AttachShader(Handle, vertexShader); - GL.AttachShader(Handle, fragmentShader); + GL.AttachShader(handle, vertexShader); + GL.AttachShader(handle, fragmentShader); // And then link them together. - LinkProgram(Handle); + LinkProgram(handle); // When the shader program is linked, it no longer needs the individual shaders attached to it; the compiled code is copied into the shader program. // Detach them, and then delete them. - GL.DetachShader(Handle, vertexShader); - GL.DetachShader(Handle, fragmentShader); + GL.DetachShader(handle, vertexShader); + GL.DetachShader(handle, fragmentShader); GL.DeleteShader(fragmentShader); GL.DeleteShader(vertexShader); - // The shader is now ready to go, but first, we're going to cache all the shader uniform locations. - // Querying this from the shader is very slow, so we do it once on initialization and reuse those values - // later. - - // First, we have to get the number of active uniforms in the shader. - GL.GetProgram(Handle, GetProgramParameterName.ActiveUniforms, out var numberOfUniforms); - - // Next, allocate the dictionary to hold the locations. - _uniformLocations = new Dictionary(); - - // Loop over all the uniforms, - for (var i = 0; i < numberOfUniforms; i++) - { - // get the name of this uniform, - var key = GL.GetActiveUniform(Handle, i, out _, out _); - - // get the location, - var location = GL.GetUniformLocation(Handle, key); - - // and then add it to the dictionary. - _uniformLocations.Add(key, location); - } + return handle; } private static void CompileShader(int shader) @@ -114,76 +112,25 @@ private static void LinkProgram(int program) throw new Exception($"Error occurred whilst linking Program({program})"); } } + } - // A wrapper function that enables the shader program. - public void Use() - { - GL.UseProgram(Handle); - } - - // The shader sources provided with this project use hardcoded layout(location)-s. If you want to do it dynamically, - // you can omit the layout(location=X) lines in the vertex shader, and use this in VertexAttribPointer instead of the hardcoded values. - public int GetAttribLocation(string attribName) - { - return GL.GetAttribLocation(Handle, attribName); - } - - // Uniform setters - // Uniforms are variables that can be set by user code, instead of reading them from the VBO. - // You use VBOs for vertex-related data, and uniforms for almost everything else. - - // Setting a uniform is almost always the exact same, so I'll explain it here once, instead of in every method: - // 1. Bind the program you want to set the uniform on - // 2. Get a handle to the location of the uniform with GL.GetUniformLocation. - // 3. Use the appropriate GL.Uniform* function to set the uniform. - - /// - /// Set a uniform int on this shader. - /// - /// The name of the uniform - /// The data to set - public void SetInt(string name, int data) - { - GL.UseProgram(Handle); - GL.Uniform1(_uniformLocations[name], data); - } + // A simple class that can be used to associate a uniform location dictionary to a shader program. + public class Shader + { + public readonly int Handle; - /// - /// Set a uniform float on this shader. - /// - /// The name of the uniform - /// The data to set - public void SetFloat(string name, float data) - { - GL.UseProgram(Handle); - GL.Uniform1(_uniformLocations[name], data); - } + public readonly Dictionary UniformLocations; - /// - /// Set a uniform Matrix4 on this shader - /// - /// The name of the uniform - /// The data to set - /// - /// - /// The matrix is transposed before being sent to the shader. - /// - /// - public void SetMatrix4(string name, Matrix4 data) + public Shader(string vertexPath, string fragmentPath) { - GL.UseProgram(Handle); - GL.UniformMatrix4(_uniformLocations[name], true, ref data); + Handle = ShaderUtils.Compile(vertexPath, fragmentPath); + UniformLocations = ShaderUtils.CreateUniformLocationsDict(Handle); } - /// - /// Set a uniform Vector3 on this shader. - /// - /// The name of the uniform - /// The data to set - public void SetVector3(string name, Vector3 data) + public Shader(int handle, Dictionary uniformLocations) { - GL.UseProgram(Handle); - GL.Uniform3(_uniformLocations[name], data); + Handle = handle; + UniformLocations = uniformLocations; } } } From d393b32c0f3ac32b2c58561c44bf3eb9a4b5fbda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4ger?= Date: Thu, 18 Jan 2024 23:20:35 +0100 Subject: [PATCH 2/2] Un-oop:ed the Shader and Texture classes some more. --- Chapter1/2-HelloTriangle/Window.cs | 2 +- Chapter1/3-ElementBufferObjects/Window.cs | 2 +- Chapter1/4-Shaders-InsAndOuts/Window.cs | 2 +- Chapter1/4-Shaders-MoreAttributes/Window.cs | 2 +- Chapter1/4-Shaders-Uniforms/Window.cs | 2 +- Chapter1/5-Textures/Window.cs | 11 +- Chapter1/6-MultipleTextures/Window.cs | 24 ++-- Chapter1/7-Transformations/Window.cs | 19 +-- Chapter1/8-CoordinatesSystems/Window.cs | 19 +-- Chapter1/9-Camera/Window.cs | 19 +-- Chapter2/1-Colors/Window.cs | 4 +- Chapter2/2-BasicLighting/Window.cs | 4 +- Chapter2/3-Materials/Window.cs | 4 +- Chapter2/4-LightingMaps/Window.cs | 15 ++- .../Window.cs | 15 ++- Chapter2/5-LightCasters-PointLights/Window.cs | 15 ++- Chapter2/5-LightCasters-Spotlight/Window.cs | 15 ++- Chapter2/6-MultipleLights/Window.cs | 14 ++- Common/Shader.cs | 118 +++++++++--------- Common/Texture.cs | 23 +--- 20 files changed, 173 insertions(+), 156 deletions(-) diff --git a/Chapter1/2-HelloTriangle/Window.cs b/Chapter1/2-HelloTriangle/Window.cs index e37c319..1f57f75 100644 --- a/Chapter1/2-HelloTriangle/Window.cs +++ b/Chapter1/2-HelloTriangle/Window.cs @@ -114,7 +114,7 @@ protected override void OnLoad() // Shaders are tiny programs that live on the GPU. OpenGL uses them to handle the vertex-to-pixel pipeline. // Check out the Shader class in Common to see how we create our shaders, as well as a more in-depth explanation of how shaders work. // shader.vert and shader.frag contain the actual shader code. - _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _shader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); // Now, enable the shader. // Just like the VBO, this is global, so every function that uses a shader will modify this one until a new one is bound instead. diff --git a/Chapter1/3-ElementBufferObjects/Window.cs b/Chapter1/3-ElementBufferObjects/Window.cs index 92539f3..2208ca2 100644 --- a/Chapter1/3-ElementBufferObjects/Window.cs +++ b/Chapter1/3-ElementBufferObjects/Window.cs @@ -76,7 +76,7 @@ protected override void OnLoad() GL.BufferData(BufferTarget.ElementArrayBuffer, _indices.Length * sizeof(uint), _indices, BufferUsageHint.StaticDraw); // The EBO has now been properly setup. Go to the Render function to see how we draw our rectangle now! - _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _shader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); GL.UseProgram(_shader.Handle); } diff --git a/Chapter1/4-Shaders-InsAndOuts/Window.cs b/Chapter1/4-Shaders-InsAndOuts/Window.cs index 5ca3951..dce7624 100644 --- a/Chapter1/4-Shaders-InsAndOuts/Window.cs +++ b/Chapter1/4-Shaders-InsAndOuts/Window.cs @@ -56,7 +56,7 @@ protected override void OnLoad() GL.GetInteger(GetPName.MaxVertexAttribs, out int maxAttributeCount); Debug.WriteLine($"Maximum number of vertex attributes supported: {maxAttributeCount}"); - _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _shader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); GL.UseProgram(_shader.Handle); } diff --git a/Chapter1/4-Shaders-MoreAttributes/Window.cs b/Chapter1/4-Shaders-MoreAttributes/Window.cs index 279d094..4c5f74f 100644 --- a/Chapter1/4-Shaders-MoreAttributes/Window.cs +++ b/Chapter1/4-Shaders-MoreAttributes/Window.cs @@ -67,7 +67,7 @@ protected override void OnLoad() GL.GetInteger(GetPName.MaxVertexAttribs, out int maxAttributeCount); Debug.WriteLine($"Maximum number of vertex attributes supported: {maxAttributeCount}"); - _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _shader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); GL.UseProgram(_shader.Handle); } diff --git a/Chapter1/4-Shaders-Uniforms/Window.cs b/Chapter1/4-Shaders-Uniforms/Window.cs index a09f956..5b146dc 100644 --- a/Chapter1/4-Shaders-Uniforms/Window.cs +++ b/Chapter1/4-Shaders-Uniforms/Window.cs @@ -56,7 +56,7 @@ protected override void OnLoad() GL.GetInteger(GetPName.MaxVertexAttribs, out int maxAttributeCount); Debug.WriteLine($"Maximum number of vertex attributes supported: {maxAttributeCount}"); - _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _shader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); GL.UseProgram(_shader.Handle); // We start the stopwatch here as this method is only called once. diff --git a/Chapter1/5-Textures/Window.cs b/Chapter1/5-Textures/Window.cs index 71f2df6..4689e9e 100644 --- a/Chapter1/5-Textures/Window.cs +++ b/Chapter1/5-Textures/Window.cs @@ -35,7 +35,7 @@ public class Window : GameWindow private Shader _shader; // For documentation on this, check Texture.cs. - private Texture _texture; + private int _texture; public Window(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings) : base(gameWindowSettings, nativeWindowSettings) @@ -60,7 +60,7 @@ protected override void OnLoad() GL.BufferData(BufferTarget.ElementArrayBuffer, _indices.Length * sizeof(uint), _indices, BufferUsageHint.StaticDraw); // The shaders have been modified to include the texture coordinates, check them out after finishing the OnLoad function. - _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _shader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); GL.UseProgram(_shader.Handle); // Because there's now 5 floats between the start of the first vertex and the start of the second, @@ -78,7 +78,8 @@ protected override void OnLoad() GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); _texture = Texture.LoadFromFile("Resources/container.png"); - _texture.Use(TextureUnit.Texture0); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _texture); } protected override void OnRenderFrame(FrameEventArgs e) @@ -89,7 +90,9 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vertexArrayObject); - _texture.Use(TextureUnit.Texture0); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _texture); + GL.UseProgram(_shader.Handle); GL.DrawElements(PrimitiveType.Triangles, _indices.Length, DrawElementsType.UnsignedInt, 0); diff --git a/Chapter1/6-MultipleTextures/Window.cs b/Chapter1/6-MultipleTextures/Window.cs index eeac115..c02ceb0 100644 --- a/Chapter1/6-MultipleTextures/Window.cs +++ b/Chapter1/6-MultipleTextures/Window.cs @@ -31,9 +31,9 @@ public class Window : GameWindow private Shader _shader; - private Texture _texture; + private int _texture; - private Texture _texture2; + private int _texture2; public Window(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings) : base(gameWindowSettings, nativeWindowSettings) @@ -58,7 +58,7 @@ protected override void OnLoad() GL.BufferData(BufferTarget.ElementArrayBuffer, _indices.Length * sizeof(uint), _indices, BufferUsageHint.StaticDraw); // shader.frag has been modified yet again, take a look at it as well. - _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _shader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); GL.UseProgram(_shader.Handle); var vertexLocation = 0; // The location of aPos @@ -72,14 +72,19 @@ protected override void OnLoad() _texture = Texture.LoadFromFile("Resources/container.png"); // Texture units are explained in Texture.cs, at the Use function. // First texture goes in texture unit 0. - _texture.Use(TextureUnit.Texture0); + + // First we use GL.ActiveTexture to tell OpenGL which texture unit we would like following commands to use. + GL.ActiveTexture(TextureUnit.Texture0); + // Then we bind our first texture to the 0th texture unit as a 2D texture. + GL.BindTexture(TextureTarget.Texture2D, _texture); // This is helpful because System.Drawing reads the pixels differently than OpenGL expects. _texture2 = Texture.LoadFromFile("Resources/awesomeface.png"); // Then, the second goes in texture unit 1. - _texture2.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _texture2); - // Next, we must setup the samplers in the shaders to use the right textures. + // Next, we must setup the samplers in the shaders to use the right texture units. // The int we send to the uniform indicates which texture unit the sampler should use. GL.Uniform1(_shader.UniformLocations["texture0"], 0); GL.Uniform1(_shader.UniformLocations["texture1"], 1); @@ -93,8 +98,11 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vertexArrayObject); - _texture.Use(TextureUnit.Texture0); - _texture2.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _texture); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _texture2); + GL.UseProgram(_shader.Handle); GL.DrawElements(PrimitiveType.Triangles, _indices.Length, DrawElementsType.UnsignedInt, 0); diff --git a/Chapter1/7-Transformations/Window.cs b/Chapter1/7-Transformations/Window.cs index f65e766..e931bb2 100644 --- a/Chapter1/7-Transformations/Window.cs +++ b/Chapter1/7-Transformations/Window.cs @@ -41,9 +41,9 @@ public class Window : GameWindow private Shader _shader; - private Texture _texture; + private int _texture; - private Texture _texture2; + private int _texture2; public Window(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings) : base(gameWindowSettings, nativeWindowSettings) @@ -68,7 +68,7 @@ protected override void OnLoad() GL.BufferData(BufferTarget.ElementArrayBuffer, _indices.Length * sizeof(uint), _indices, BufferUsageHint.StaticDraw); // shader.vert has been modified, take a look at it as well. - _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _shader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); GL.UseProgram(_shader.Handle); var vertexLocation = 0; // The location of aPos @@ -80,10 +80,12 @@ protected override void OnLoad() GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); _texture = Texture.LoadFromFile("Resources/container.png"); - _texture.Use(TextureUnit.Texture0); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _texture); _texture2 = Texture.LoadFromFile("Resources/awesomeface.png"); - _texture2.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _texture2); GL.Uniform1(_shader.UniformLocations["texture0"], 0); GL.Uniform1(_shader.UniformLocations["texture1"], 1); @@ -123,8 +125,11 @@ protected override void OnRenderFrame(FrameEventArgs e) // The next tutorial will be about how to set one up so we can use more human-readable numbers. transform = transform * Matrix4.CreateTranslation(0.1f, 0.1f, 0.0f); - _texture.Use(TextureUnit.Texture0); - _texture2.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _texture); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _texture2); + GL.UseProgram(_shader.Handle); // Now that the matrix is finished, pass it to the vertex shader. diff --git a/Chapter1/8-CoordinatesSystems/Window.cs b/Chapter1/8-CoordinatesSystems/Window.cs index d45e6cc..bcd6126 100644 --- a/Chapter1/8-CoordinatesSystems/Window.cs +++ b/Chapter1/8-CoordinatesSystems/Window.cs @@ -35,9 +35,9 @@ public class Window : GameWindow private Shader _shader; - private Texture _texture; + private int _texture; - private Texture _texture2; + private int _texture2; // We create a double to hold how long has passed since the program was opened. private double _time; @@ -78,7 +78,7 @@ protected override void OnLoad() GL.BufferData(BufferTarget.ElementArrayBuffer, _indices.Length * sizeof(uint), _indices, BufferUsageHint.StaticDraw); // shader.vert has been modified. Take a look at it after the explanation in OnRenderFrame. - _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _shader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); GL.UseProgram(_shader.Handle); var vertexLocation = 0; // The location of aPos @@ -90,10 +90,12 @@ protected override void OnLoad() GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); _texture = Texture.LoadFromFile("Resources/container.png"); - _texture.Use(TextureUnit.Texture0); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _texture); _texture2 = Texture.LoadFromFile("Resources/awesomeface.png"); - _texture2.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _texture2); GL.Uniform1(_shader.UniformLocations["texture0"], 0); GL.Uniform1(_shader.UniformLocations["texture1"], 1); @@ -124,8 +126,11 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vertexArrayObject); - _texture.Use(TextureUnit.Texture0); - _texture2.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _texture); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _texture2); + GL.UseProgram(_shader.Handle); // Finally, we have the model matrix. This determines the position of the model. diff --git a/Chapter1/9-Camera/Window.cs b/Chapter1/9-Camera/Window.cs index 6c8530e..4ed2565 100644 --- a/Chapter1/9-Camera/Window.cs +++ b/Chapter1/9-Camera/Window.cs @@ -42,9 +42,9 @@ public class Window : GameWindow private Shader _shader; - private Texture _texture; + private int _texture; - private Texture _texture2; + private int _texture2; // The view and projection matrices have been removed as we don't need them here anymore. // They can now be found in the new camera class. @@ -84,7 +84,7 @@ protected override void OnLoad() GL.BindBuffer(BufferTarget.ElementArrayBuffer, _elementBufferObject); GL.BufferData(BufferTarget.ElementArrayBuffer, _indices.Length * sizeof(uint), _indices, BufferUsageHint.StaticDraw); - _shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _shader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); GL.UseProgram(_shader.Handle); var vertexLocation = 0; // The location of aPos @@ -96,10 +96,12 @@ protected override void OnLoad() GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); _texture = Texture.LoadFromFile("Resources/container.png"); - _texture.Use(TextureUnit.Texture0); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _texture); _texture2 = Texture.LoadFromFile("Resources/awesomeface.png"); - _texture2.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _texture2); GL.Uniform1(_shader.UniformLocations["texture0"], 0); GL.Uniform1(_shader.UniformLocations["texture1"], 1); @@ -122,8 +124,11 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vertexArrayObject); - _texture.Use(TextureUnit.Texture0); - _texture2.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _texture); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _texture2); + GL.UseProgram(_shader.Handle); Matrix4 projection = _camera.GetProjectionMatrix(); diff --git a/Chapter2/1-Colors/Window.cs b/Chapter2/1-Colors/Window.cs index 97614af..70ef4d0 100644 --- a/Chapter2/1-Colors/Window.cs +++ b/Chapter2/1-Colors/Window.cs @@ -108,8 +108,8 @@ protected override void OnLoad() // Load the two different shaders, they use the same vertex shader program. However they have two different fragment shaders. // This is because the lamp only uses a basic shader to turn it white, it wouldn't make sense to have the lamp lit in other colors. // The lighting shaders uses the lighting.frag shader which is what a large part of this chapter will be about - _lightingShader = new Shader("Shaders/shader.vert", "Shaders/lighting.frag"); - _lampShader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _lightingShader = Shader.FromFile("Shaders/shader.vert", "Shaders/lighting.frag"); + _lampShader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); { // Initialize the vao for the model diff --git a/Chapter2/2-BasicLighting/Window.cs b/Chapter2/2-BasicLighting/Window.cs index 67babc2..61d50be 100644 --- a/Chapter2/2-BasicLighting/Window.cs +++ b/Chapter2/2-BasicLighting/Window.cs @@ -97,8 +97,8 @@ protected override void OnLoad() GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject); GL.BufferData(BufferTarget.ArrayBuffer, _vertices.Length * sizeof(float), _vertices, BufferUsageHint.StaticDraw); - _lightingShader = new Shader("Shaders/shader.vert", "Shaders/lighting.frag"); - _lampShader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _lightingShader = Shader.FromFile("Shaders/shader.vert", "Shaders/lighting.frag"); + _lampShader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); { _vaoModel = GL.GenVertexArray(); diff --git a/Chapter2/3-Materials/Window.cs b/Chapter2/3-Materials/Window.cs index 797b12b..516153e 100644 --- a/Chapter2/3-Materials/Window.cs +++ b/Chapter2/3-Materials/Window.cs @@ -96,8 +96,8 @@ protected override void OnLoad() GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject); GL.BufferData(BufferTarget.ArrayBuffer, _vertices.Length * sizeof(float), _vertices, BufferUsageHint.StaticDraw); - _lightingShader = new Shader("Shaders/shader.vert", "Shaders/lighting.frag"); - _lampShader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _lightingShader = Shader.FromFile("Shaders/shader.vert", "Shaders/lighting.frag"); + _lampShader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); { _vaoModel = GL.GenVertexArray(); diff --git a/Chapter2/4-LightingMaps/Window.cs b/Chapter2/4-LightingMaps/Window.cs index 83068ec..2fb4ec3 100644 --- a/Chapter2/4-LightingMaps/Window.cs +++ b/Chapter2/4-LightingMaps/Window.cs @@ -74,10 +74,10 @@ public class Window : GameWindow // The texture containing information for the diffuse map, this would more commonly // just be called the color/texture of the object. - private Texture _diffuseMap; + private int _diffuseMap; // The specular map is a black/white representation of how specular each part of the texture is. - private Texture _specularMap; + private int _specularMap; private Camera _camera; @@ -102,8 +102,8 @@ protected override void OnLoad() GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject); GL.BufferData(BufferTarget.ArrayBuffer, _vertices.Length * sizeof(float), _vertices, BufferUsageHint.StaticDraw); - _lightingShader = new Shader("Shaders/shader.vert", "Shaders/lighting.frag"); - _lampShader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _lightingShader = Shader.FromFile("Shaders/shader.vert", "Shaders/lighting.frag"); + _lampShader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); { _vaoModel = GL.GenVertexArray(); @@ -156,8 +156,11 @@ protected override void OnRenderFrame(FrameEventArgs e) // The two textures need to be used, in this case we use the diffuse map as our 0th texture // and the specular map as our 1st texture. - _diffuseMap.Use(TextureUnit.Texture0); - _specularMap.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _diffuseMap); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _specularMap); + GL.UseProgram(_lightingShader.Handle); Matrix4 projection = _camera.GetProjectionMatrix(); diff --git a/Chapter2/5-LightCasters-DirectionalLights/Window.cs b/Chapter2/5-LightCasters-DirectionalLights/Window.cs index 58c2c22..4856520 100644 --- a/Chapter2/5-LightCasters-DirectionalLights/Window.cs +++ b/Chapter2/5-LightCasters-DirectionalLights/Window.cs @@ -87,9 +87,9 @@ public class Window : GameWindow private Shader _lightingShader; - private Texture _diffuseMap; + private int _diffuseMap; - private Texture _specularMap; + private int _specularMap; private Camera _camera; @@ -114,8 +114,8 @@ protected override void OnLoad() GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject); GL.BufferData(BufferTarget.ArrayBuffer, _vertices.Length * sizeof(float), _vertices, BufferUsageHint.StaticDraw); - _lightingShader = new Shader("Shaders/shader.vert", "Shaders/lighting.frag"); - _lampShader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _lightingShader = Shader.FromFile("Shaders/shader.vert", "Shaders/lighting.frag"); + _lampShader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); { _vaoModel = GL.GenVertexArray(); @@ -161,8 +161,11 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vaoModel); - _diffuseMap.Use(TextureUnit.Texture0); - _specularMap.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _diffuseMap); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _specularMap); + GL.UseProgram(_lightingShader.Handle); Matrix4 projection = _camera.GetProjectionMatrix(); diff --git a/Chapter2/5-LightCasters-PointLights/Window.cs b/Chapter2/5-LightCasters-PointLights/Window.cs index ed09816..4948e2d 100644 --- a/Chapter2/5-LightCasters-PointLights/Window.cs +++ b/Chapter2/5-LightCasters-PointLights/Window.cs @@ -87,9 +87,9 @@ public class Window : GameWindow private Shader _lightingShader; - private Texture _diffuseMap; + private int _diffuseMap; - private Texture _specularMap; + private int _specularMap; private Camera _camera; @@ -114,8 +114,8 @@ protected override void OnLoad() GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject); GL.BufferData(BufferTarget.ArrayBuffer, _vertices.Length * sizeof(float), _vertices, BufferUsageHint.StaticDraw); - _lightingShader = new Shader("Shaders/shader.vert", "Shaders/lighting.frag"); - _lampShader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _lightingShader = Shader.FromFile("Shaders/shader.vert", "Shaders/lighting.frag"); + _lampShader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); { _vaoModel = GL.GenVertexArray(); @@ -159,8 +159,11 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vaoModel); - _diffuseMap.Use(TextureUnit.Texture0); - _specularMap.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _diffuseMap); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _specularMap); + GL.UseProgram(_lightingShader.Handle); Matrix4 projection = _camera.GetProjectionMatrix(); diff --git a/Chapter2/5-LightCasters-Spotlight/Window.cs b/Chapter2/5-LightCasters-Spotlight/Window.cs index 29ce501..ec094b2 100644 --- a/Chapter2/5-LightCasters-Spotlight/Window.cs +++ b/Chapter2/5-LightCasters-Spotlight/Window.cs @@ -89,9 +89,9 @@ public class Window : GameWindow private Shader _lightingShader; - private Texture _diffuseMap; + private int _diffuseMap; - private Texture _specularMap; + private int _specularMap; private Camera _camera; @@ -116,8 +116,8 @@ protected override void OnLoad() GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject); GL.BufferData(BufferTarget.ArrayBuffer, _vertices.Length * sizeof(float), _vertices, BufferUsageHint.StaticDraw); - _lightingShader = new Shader("Shaders/shader.vert", "Shaders/lighting.frag"); - _lampShader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _lightingShader = Shader.FromFile("Shaders/shader.vert", "Shaders/lighting.frag"); + _lampShader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); { _vaoModel = GL.GenVertexArray(); @@ -161,8 +161,11 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vaoModel); - _diffuseMap.Use(TextureUnit.Texture0); - _specularMap.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _diffuseMap); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _specularMap); + GL.UseProgram(_lightingShader.Handle); Matrix4 projection = _camera.GetProjectionMatrix(); diff --git a/Chapter2/6-MultipleLights/Window.cs b/Chapter2/6-MultipleLights/Window.cs index 2101691..2052470 100644 --- a/Chapter2/6-MultipleLights/Window.cs +++ b/Chapter2/6-MultipleLights/Window.cs @@ -91,9 +91,9 @@ public class Window : GameWindow private Shader _lightingShader; - private Texture _diffuseMap; + private int _diffuseMap; - private Texture _specularMap; + private int _specularMap; private Camera _camera; @@ -118,8 +118,8 @@ protected override void OnLoad() GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferObject); GL.BufferData(BufferTarget.ArrayBuffer, _vertices.Length * sizeof(float), _vertices, BufferUsageHint.StaticDraw); - _lightingShader = new Shader("Shaders/shader.vert", "Shaders/lighting.frag"); - _lampShader = new Shader("Shaders/shader.vert", "Shaders/shader.frag"); + _lightingShader = Shader.FromFile("Shaders/shader.vert", "Shaders/lighting.frag"); + _lampShader = Shader.FromFile("Shaders/shader.vert", "Shaders/shader.frag"); { _vaoModel = GL.GenVertexArray(); @@ -163,8 +163,10 @@ protected override void OnRenderFrame(FrameEventArgs e) GL.BindVertexArray(_vaoModel); - _diffuseMap.Use(TextureUnit.Texture0); - _specularMap.Use(TextureUnit.Texture1); + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, _diffuseMap); + GL.ActiveTexture(TextureUnit.Texture1); + GL.BindTexture(TextureTarget.Texture2D, _specularMap); GL.UseProgram(_lightingShader.Handle); Matrix4 projection = _camera.GetProjectionMatrix(); diff --git a/Common/Shader.cs b/Common/Shader.cs index 2e0a66c..a1418f4 100644 --- a/Common/Shader.cs +++ b/Common/Shader.cs @@ -6,62 +6,41 @@ using OpenTK.Mathematics; using System.Reflection.Metadata; using System.ComponentModel; +using OpenTK.Compute.OpenCL; namespace LearnOpenTK.Common { - public static class ShaderUtils + // A simple class that can be used to associate a uniform location dictionary to a shader program. + public class Shader { - // This function creates a dictionary that maps uniform names to their location, - // this is used to speed up uniform location queries. - public static Dictionary CreateUniformLocationsDict(int program) - { - // First, we have to get the number of active uniforms in the shader. - GL.GetProgram(program, GetProgramParameterName.ActiveUniforms, out var numberOfUniforms); - - // Next, allocate the dictionary to hold the locations. - Dictionary uniformLocations = new Dictionary(); - - // Loop over all the uniforms, - for (var i = 0; i < numberOfUniforms; i++) - { - // get the name of this uniform, - var key = GL.GetActiveUniform(program, i, out _, out _); - - // get the location, - var location = GL.GetUniformLocation(program, key); - - // and then add it to the dictionary. - uniformLocations.Add(key, location); - } + public readonly int Handle; - return uniformLocations; - } + public readonly Dictionary UniformLocations; - public static int Compile(string vertexPath, string fragmentPath) + public static Shader FromFile(string vertexPath, string fragmentPath) { // There are several different types of shaders, but the only two you need for basic rendering are the vertex and fragment shaders. // The vertex shader is responsible for moving around vertices, and uploading that data to the fragment shader. - // The vertex shader won't be too important here, but they'll be more important later. // The fragment shader is responsible for then converting the vertices to "fragments", which represent all the data OpenGL needs to draw a pixel. - // The fragment shader is what we'll be using the most here. // Load vertex shader and compile - var shaderSource = File.ReadAllText(vertexPath); + string vertexSource = File.ReadAllText(vertexPath); + string fragmentSource = File.ReadAllText(fragmentPath); - // GL.CreateShader will create an empty shader (obviously). The ShaderType enum denotes which type of shader will be created. - var vertexShader = GL.CreateShader(ShaderType.VertexShader); + int program = CompileProgram(vertexSource, fragmentSource); - // Now, bind the GLSL source code - GL.ShaderSource(vertexShader, shaderSource); + Dictionary uniformLocations = CreateUniformLocationsDict(program); - // And then compile - CompileShader(vertexShader); + return new Shader(program, uniformLocations); + } + + private static int CompileProgram(string vertexSource, string fragmentSource) + { + // Compile vertex shader. + int vertexShader = CompileShader(ShaderType.VertexShader, vertexSource); // We do the same for the fragment shader. - shaderSource = File.ReadAllText(fragmentPath); - var fragmentShader = GL.CreateShader(ShaderType.FragmentShader); - GL.ShaderSource(fragmentShader, shaderSource); - CompileShader(fragmentShader); + int fragmentShader = CompileShader(ShaderType.FragmentShader, fragmentSource); // These two shaders must then be merged into a shader program, which can then be used by OpenGL. // To do this, create a program... @@ -72,7 +51,16 @@ public static int Compile(string vertexPath, string fragmentPath) GL.AttachShader(handle, fragmentShader); // And then link them together. - LinkProgram(handle); + GL.LinkProgram(handle); + + // Check for linking errors + GL.GetProgram(handle, GetProgramParameterName.LinkStatus, out var code); + if (code != (int)All.True) + { + // We can use `GL.GetProgramInfoLog(program)` to get information about the error. + string infoLog = GL.GetProgramInfoLog(handle); + throw new Exception($"Error occurred whilst linking Program({handle}):\n{infoLog}"); + }; // When the shader program is linked, it no longer needs the individual shaders attached to it; the compiled code is copied into the shader program. // Detach them, and then delete them. @@ -84,8 +72,14 @@ public static int Compile(string vertexPath, string fragmentPath) return handle; } - private static void CompileShader(int shader) + private static int CompileShader(ShaderType type, string source) { + // GL.CreateShader will create an empty shader. The ShaderType enum denotes which type of shader will be created. + int shader = GL.CreateShader(type); + + // Upload the GLSL source code. + GL.ShaderSource(shader, source); + // Try to compile the shader GL.CompileShader(shader); @@ -95,36 +89,36 @@ private static void CompileShader(int shader) { // We can use `GL.GetShaderInfoLog(shader)` to get information about the error. var infoLog = GL.GetShaderInfoLog(shader); - throw new Exception($"Error occurred whilst compiling Shader({shader}).\n\n{infoLog}"); + throw new Exception($"Error occurred whilst compiling Shader({shader}):\n{infoLog}"); } + + return shader; } - private static void LinkProgram(int program) + // This function creates a dictionary that maps uniform names to their location, + // this is used to speed up uniform location queries. + public static Dictionary CreateUniformLocationsDict(int program) { - // We link the program - GL.LinkProgram(program); + // First, we have to get the number of active uniforms in the shader. + GL.GetProgram(program, GetProgramParameterName.ActiveUniforms, out var numberOfUniforms); - // Check for linking errors - GL.GetProgram(program, GetProgramParameterName.LinkStatus, out var code); - if (code != (int)All.True) + // Next, allocate the dictionary to hold the locations. + Dictionary uniformLocations = new Dictionary(); + + // Loop over all the uniforms, + for (var i = 0; i < numberOfUniforms; i++) { - // We can use `GL.GetProgramInfoLog(program)` to get information about the error. - throw new Exception($"Error occurred whilst linking Program({program})"); - } - } - } + // get the name of this uniform, + var key = GL.GetActiveUniform(program, i, out _, out _); - // A simple class that can be used to associate a uniform location dictionary to a shader program. - public class Shader - { - public readonly int Handle; + // get the location, + var location = GL.GetUniformLocation(program, key); - public readonly Dictionary UniformLocations; + // and then add it to the dictionary. + uniformLocations.Add(key, location); + } - public Shader(string vertexPath, string fragmentPath) - { - Handle = ShaderUtils.Compile(vertexPath, fragmentPath); - UniformLocations = ShaderUtils.CreateUniformLocationsDict(Handle); + return uniformLocations; } public Shader(int handle, Dictionary uniformLocations) diff --git a/Common/Texture.cs b/Common/Texture.cs index b9bde62..9e6bf0e 100755 --- a/Common/Texture.cs +++ b/Common/Texture.cs @@ -8,11 +8,9 @@ namespace LearnOpenTK.Common { // A helper class, much like Shader, meant to simplify loading textures. - public class Texture + public static class Texture { - public readonly int Handle; - - public static Texture LoadFromFile(string path) + public static int LoadFromFile(string path) { // Generate handle int handle = GL.GenTexture(); @@ -70,22 +68,7 @@ public static Texture LoadFromFile(string path) // Here is an example of mips in action https://en.wikipedia.org/wiki/File:Mipmap_Aliasing_Comparison.png GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); - return new Texture(handle); - } - - public Texture(int glHandle) - { - Handle = glHandle; - } - - // Activate texture - // Multiple textures can be bound, if your shader needs more than just one. - // If you want to do that, use GL.ActiveTexture to set which slot GL.BindTexture binds to. - // The OpenGL standard requires that there be at least 16, but there can be more depending on your graphics card. - public void Use(TextureUnit unit) - { - GL.ActiveTexture(unit); - GL.BindTexture(TextureTarget.Texture2D, Handle); + return handle; } } }