diff --git a/lib/game_objects/light.rb b/lib/game_objects/light.rb index 53ae0a6..f215405 100644 --- a/lib/game_objects/light.rb +++ b/lib/game_objects/light.rb @@ -2,9 +2,10 @@ class IMICFPS class Light DIRECTIONAL = 0 POINT = 1 + SPOT = 2 attr_reader :light_id - attr_accessor :type, :ambient, :diffuse, :specular, :position, :intensity + attr_accessor :type, :ambient, :diffuse, :specular, :position, :direction, :intensity def initialize( id:, type: Light::POINT, @@ -12,6 +13,7 @@ class IMICFPS diffuse: Vector.new(1, 1, 1), specular: Vector.new(0.2, 0.2, 0.2), position: Vector.new(0, 0, 0), + direction: Vector.new(0, 0, 0), intensity: 1 ) @light_id = id @@ -21,6 +23,7 @@ class IMICFPS @diffuse = diffuse @specular = specular @position = position + @direction = direction @intensity = intensity end diff --git a/lib/model.rb b/lib/model.rb index ee2507f..956cc82 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -119,11 +119,6 @@ class IMICFPS buffer = " " * 4 glGenBuffers(1, buffer) @uvs_buffer_id = buffer.unpack('L2').first - - @textures_buffer_id = nil - buffer = " " * 4 - glGenBuffers(1, buffer) - @textures_buffer_id = buffer.unpack('L2').first end def populate_vertex_buffer @@ -131,7 +126,6 @@ class IMICFPS colors = [] norms = [] uvs = [] - tex_ids = [] @faces.each do |face| pos << face.vertices.map { |vert| [vert.x, vert.y, vert.z] } @@ -140,7 +134,6 @@ class IMICFPS if has_texture? uvs << face.uvs.map { |vert| [vert.x, vert.y, vert.z] } - tex_ids << face.material.texture_id ? face.material.texture_id.to_f : -1.0 end end @@ -156,9 +149,6 @@ class IMICFPS if has_texture? glBindBuffer(GL_ARRAY_BUFFER, @uvs_buffer_id) glBufferData(GL_ARRAY_BUFFER, uvs.flatten.size * Fiddle::SIZEOF_FLOAT, uvs.flatten.pack("f*"), GL_STATIC_DRAW) - - # glBindBuffer(GL_ARRAY_BUFFER, @textures_buffer_id) - # glBufferData(GL_ARRAY_BUFFER, tex_ids.flatten.size * Fiddle::SIZEOF_FLOAT, tex_ids.flatten.pack("f*"), GL_STATIC_DRAW) end glBindBuffer(GL_ARRAY_BUFFER, 0) @@ -193,11 +183,6 @@ class IMICFPS # inUV glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, nil) gl_error? - # texture ids - glBindBuffer(GL_ARRAY_BUFFER, @textures_buffer_id) - # inTextureID - glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, 0, nil) - gl_error? end glBindBuffer(GL_ARRAY_BUFFER, 0) diff --git a/lib/renderer/g_buffer.rb b/lib/renderer/g_buffer.rb index 5388caf..976d804 100644 --- a/lib/renderer/g_buffer.rb +++ b/lib/renderer/g_buffer.rb @@ -127,6 +127,9 @@ class IMICFPS glBufferData(GL_ARRAY_BUFFER, @uvs.size * Fiddle::SIZEOF_FLOAT, @uvs.pack("f*"), GL_STATIC_DRAW); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nil) + glEnableVertexAttribArray(0) + glEnableVertexAttribArray(1) + glBindVertexArray(0) end diff --git a/lib/renderer/opengl_renderer.rb b/lib/renderer/opengl_renderer.rb index bc75de3..63438dc 100644 --- a/lib/renderer/opengl_renderer.rb +++ b/lib/renderer/opengl_renderer.rb @@ -16,27 +16,16 @@ class IMICFPS end def render(camera, lights, entities) - if window.config.get(:debug_options, :use_shaders) && Shader.available?("default") && Shader.available?("render_screen") + if window.config.get(:debug_options, :use_shaders) && Shader.available?("g_buffer") && Shader.available?("deferred_lighting") @g_buffer.bind_for_writing gl_error? glClearColor(0.0, 0.0, 0.0, 0.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) - Shader.use("default") do |shader| - lights.each_with_index do |light, i| - shader.uniform_float("lights[#{i}.end", -1.0); - shader.uniform_float("lights[#{i}.type", light.type); - shader.uniform_vec3("lights[#{i}].position", light.position) - shader.uniform_vec3("lights[#{i}].ambient", light.ambient) - shader.uniform_vec3("lights[#{i}].diffuse", light.diffuse) - shader.uniform_vec3("lights[#{i}].specular", light.specular) - end + Shader.use("g_buffer") do |shader| gl_error? - - shader.uniform_integer("totalLights", lights.size) - entities.each do |entity| next unless entity.visible && entity.renderable @@ -54,7 +43,6 @@ class IMICFPS @g_buffer.unbind_framebuffer gl_error? - @g_buffer.bind_for_reading glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) @@ -65,7 +53,7 @@ class IMICFPS @g_buffer.unbind_framebuffer gl_error? else - puts "Shader 'default' failed to compile, using immediate mode for rendering..." unless @@immediate_mode_warning + puts "Shaders are disabled or failed to compile, using immediate mode for rendering..." unless @@immediate_mode_warning @@immediate_mode_warning = true gl_error? @@ -94,7 +82,7 @@ class IMICFPS gl_error? end - def lighting(lights) + def copy_g_buffer_to_screen @g_buffer.set_read_buffer(:position) glBlitFramebuffer(0, 0, @g_buffer.width, @g_buffer.height, 0, 0, @g_buffer.width / 2, @g_buffer.height / 2, @@ -116,15 +104,50 @@ class IMICFPS GL_COLOR_BUFFER_BIT, GL_LINEAR) end + def lighting(lights) + Shader.use("deferred_lighting") do |shader| + lights.each_with_index do |light, i| + shader.uniform_float("light.type", light.type); + shader.uniform_vec3("light.direction", light.direction) + shader.uniform_vec3("light.position", light.position) + shader.uniform_vec3("light.ambient", light.ambient) + shader.uniform_vec3("light.diffuse", light.diffuse) + shader.uniform_vec3("light.specular", light.specular) + + glBindVertexArray(@g_buffer.screen_vbo) + + glDisable(GL_DEPTH_TEST) + glEnable(GL_BLEND) + + glActiveTexture(GL_TEXTURE0) + glBindTexture(GL_TEXTURE_2D, @g_buffer.texture(:diffuse)) + + glActiveTexture(GL_TEXTURE1) + glBindTexture(GL_TEXTURE_2D, @g_buffer.texture(:position)) + + glActiveTexture(GL_TEXTURE2) + glBindTexture(GL_TEXTURE_2D, @g_buffer.texture(:texcoord)) + + glActiveTexture(GL_TEXTURE3) + glBindTexture(GL_TEXTURE_2D, @g_buffer.texture(:normal)) + + glActiveTexture(GL_TEXTURE4) + glBindTexture(GL_TEXTURE_2D, @g_buffer.texture(:depth)) + + glDrawArrays(GL_TRIANGLES, 0, @g_buffer.vertices.size) + + glBindVertexArray(0) + end + end + end + def post_processing end def render_framebuffer - if Shader.available?("render_screen") - Shader.use("render_screen") do |shader| + if Shader.available?("deferred_lighting") + Shader.use("deferred_lighting") do |shader| glBindVertexArray(@g_buffer.screen_vbo) - glEnableVertexAttribArray(0) - glEnableVertexAttribArray(1) glDisable(GL_DEPTH_TEST) glEnable(GL_BLEND) @@ -134,8 +157,6 @@ class IMICFPS glDrawArrays(GL_TRIANGLES, 0, @g_buffer.vertices.size) - glDisableVertexAttribArray(1) - glDisableVertexAttribArray(0) glBindVertexArray(0) end end diff --git a/lib/renderer/renderer.rb b/lib/renderer/renderer.rb index 31a30d5..60810cb 100644 --- a/lib/renderer/renderer.rb +++ b/lib/renderer/renderer.rb @@ -10,7 +10,7 @@ class IMICFPS end def preload_default_shaders - shaders = ["default", "render_screen"] + shaders = ["g_buffer", "deferred_lighting"] shaders.each do |shader| Shader.new( name: shader, diff --git a/lib/tools/asset_viewer/lib/turn_table.rb b/lib/tools/asset_viewer/lib/turn_table.rb index 38209ef..25e4f2b 100644 --- a/lib/tools/asset_viewer/lib/turn_table.rb +++ b/lib/tools/asset_viewer/lib/turn_table.rb @@ -8,15 +8,6 @@ class IMICFPS window.needs_cursor = false @manifest = @options[:manifest] - if window.config.get(:debug_options, :use_shaders) && !Shader.available?("default") - Shader.new( - name: "default", - includes_dir: "shaders/include", - vertex: "shaders/vertex/default.glsl", - fragment: "shaders/fragment/default.glsl" - ) - end - @map = ProtoMap.new Publisher.new @@ -27,7 +18,7 @@ class IMICFPS @crosshair = Crosshair.new(color: Gosu::Color.rgba(100, 200, 255, 100)) @lights = [] - @light = Light.new(id: available_light, position: Vector.new, diffuse: Vector.new(1, 1, 1, 1)) + @light = Light.new(type: Light::DIRECTIONAL, id: available_light, position: Vector.new, diffuse: Vector.new(1, 1, 1, 1)) @lights << @light @camera = Camera.new(position: Vector.new(0, 1.5, 5), orientation: Vector.forward) diff --git a/shaders/fragment/default.glsl b/shaders/fragment/default.glsl deleted file mode 100644 index 6952ff0..0000000 --- a/shaders/fragment/default.glsl +++ /dev/null @@ -1,108 +0,0 @@ -# version 330 core - -@include "light_struct" - -layout(location = 0) out vec3 fragPosition; -layout (location = 1) out vec4 fragColor; -layout (location = 2) out vec3 fragNormal; -layout (location = 3) out vec3 fragUV; - -in vec3 outPosition; -in vec3 outColor; -in vec3 outNormal; -in vec3 outUV; -in float outTextureID; -in Light outLights[MAX_LIGHTS]; -flat in int outTotalLights; -in vec3 outFragPos; -in vec3 outCameraPos; -flat in int outHasTexture; -flat in int outDisableLighting; - -uniform sampler2D diffuse_texture; - -// optimizing compilers are annoying at this stage of my understanding of GLSL -vec4 lokiVar; - -// https://learnopengl.com/Lighting/Multiple-lights -vec3 calculatePointLight(Light light) { - vec3 viewDir = normalize(outCameraPos - outFragPos); - vec3 lightDir = normalize(light.position - outFragPos); - float diff = max(dot(vec3(outNormal), lightDir), 0.0); - vec3 reflectDir = reflect(-lightDir, vec3(outNormal)); - float spec = pow(max(dot(viewDir, reflectDir), 0.0), 16.0); - - float distance = length(light.position - outFragPos); - float attenuation = 1.0 / (1.0 + 0.09 * distance + - 0.032 * (distance * distance)); - - vec3 ambient = light.ambient * outColor; - vec3 diffuse = light.diffuse * outColor; - vec3 specular = light.specular * spec * vec3(1.0, 1.0, 1.0); - - ambient *= attenuation; - diffuse *= attenuation; - specular *= attenuation; - - return (ambient + diffuse + specular); -} - -// https://learnopengl.com/Lighting/Basic-Lighting -vec3 calculateBasicLight(Light light) { - vec3 lightDir = normalize(light.position - outFragPos); - - float ambientStrength = 0.25; - vec3 ambient = ambientStrength * light.ambient; - - float diff = max(dot(normalize(vec3(outNormal)), lightDir), 0.0); - vec3 diffuse = diff * light.diffuse; - - float specularStrength = 0.5; - vec3 viewDir = normalize(outCameraPos - outFragPos); - vec3 reflectDir = reflect(-lightDir, outNormal); - float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); - vec3 specular = specularStrength * spec * light.specular; - - return vec3(ambient + diffuse + specular); -} - -vec3 calculateLighting() { - vec3 result = vec3(0.0, 0.0, 0.0); - - for (int i = 0; i < min(outTotalLights, MAX_LIGHTS); i++) { - if (int(outLights[i].type) == 0) { - result += calculateBasicLight(outLights[i]); - } else if (int(outLights[i].type) == 1) { - result += calculateBasicLight(outLights[i]); - } - } - - return result; -} - -void main() { - lokiVar = vec4(outColor, 1.0) + vec4(outNormal, 1.0) + vec4(outUV, 1.0) + vec4(outTextureID, 1.0, 1.0, 1.0); - lokiVar = normalize(lokiVar); - - vec3 result; - - if (outHasTexture == 0) { - if (outDisableLighting == 1.0) { - result = outColor + 0.25; - } else { - result = calculateLighting() * outColor; - } - - } else { - if (outDisableLighting == 1.0) { - result = texture(diffuse_texture, outUV.xy).xyz + 0.25; - } else { - result = calculateLighting() * texture(diffuse_texture, outUV.xy).xyz; - } - } - - fragPosition = outPosition; - fragColor = vec4(result, 1.0); - fragNormal = outNormal; - fragUV = outUV; -} diff --git a/shaders/fragment/deferred_lighting.glsl b/shaders/fragment/deferred_lighting.glsl new file mode 100644 index 0000000..e1e4593 --- /dev/null +++ b/shaders/fragment/deferred_lighting.glsl @@ -0,0 +1,35 @@ +#version 330 core +out vec4 FragColor; + +@include "light_struct" +const int DIRECTIONAL = 0; +const int POINT = 1; +const int SPOT = 2; + +in vec2 outTexCoords; +flat in Light outLight; + +uniform sampler2D diffuse, position, texcoord, normal, depth; + +vec4 directionalLight(Light light) { + return vec4(0,0,0,0); +} + +vec4 calculateLighting(Light light) { + vec4 result = vec4(0,0,0,0); + + switch(light.type) { + case DIRECTIONAL: { + result = directionalLight(light); + } + default: { + result = vec4(1,1,1,1); + } + } + + return result; +} + +void main() { + FragColor = texture(diffuse, outTexCoords) * calculateLighting(outLight); +} \ No newline at end of file diff --git a/shaders/fragment/g_buffer.glsl b/shaders/fragment/g_buffer.glsl new file mode 100644 index 0000000..1638f29 --- /dev/null +++ b/shaders/fragment/g_buffer.glsl @@ -0,0 +1,26 @@ +# version 330 core + +layout(location = 0) out vec3 fragPosition; +layout (location = 1) out vec4 fragColor; +layout (location = 2) out vec3 fragNormal; +layout (location = 3) out vec3 fragUV; + +in vec3 outPosition, outColor, outNormal, outUV, outFragPos, outCameraPos; +flat in int outHasTexture; + +uniform sampler2D diffuse_texture; + +void main() { + vec3 result; + + if (outHasTexture == 0) { + result = outColor; + } else { + result = texture(diffuse_texture, outUV.xy).xyz + 0.25; + } + + fragPosition = outPosition; + fragColor = vec4(result, 1.0); + fragNormal = outNormal; + fragUV = outUV; +} diff --git a/shaders/fragment/render_screen.glsl b/shaders/fragment/render_screen.glsl deleted file mode 100644 index 0826a98..0000000 --- a/shaders/fragment/render_screen.glsl +++ /dev/null @@ -1,10 +0,0 @@ -#version 330 core -out vec4 FragColor; - -in vec2 outTexCoords; - -uniform sampler2D screenTexture; - -void main() { - FragColor = texture(screenTexture, outTexCoords); -} \ No newline at end of file diff --git a/shaders/include/light_struct.glsl b/shaders/include/light_struct.glsl index b5ecb7e..6a18d09 100644 --- a/shaders/include/light_struct.glsl +++ b/shaders/include/light_struct.glsl @@ -1,15 +1,11 @@ -const int MAX_LIGHTS = 2; - struct Light { - float end; - float type; + int type; + vec3 direction; vec3 position; vec3 diffuse; vec3 ambient; vec3 specular; - vec3 direction; - float intensity; }; diff --git a/shaders/vertex/default.glsl b/shaders/vertex/default.glsl deleted file mode 100644 index f864df6..0000000 --- a/shaders/vertex/default.glsl +++ /dev/null @@ -1,50 +0,0 @@ -# version 330 core - -@include "light_struct" - -layout(location = 0) in vec3 inPosition; -layout(location = 1) in vec3 inColor; -layout(location = 2) in vec3 inNormal; -layout(location = 3) in vec3 inUV; -layout(location = 4) in float inTextureID; - -out vec3 outPosition; -out vec3 outColor; -out vec3 outNormal; -out vec3 outUV; -out float outTextureID; -out Light outLights[MAX_LIGHTS]; -flat out int outTotalLights; -out vec3 outFragPos; -out vec3 outViewPos; -out vec3 outCameraPos; -flat out int outHasTexture; -flat out int outDisableLighting; - -uniform mat4 projection; -uniform mat4 view; -uniform mat4 model; -uniform int hasTexture; -uniform int totalLights; -uniform Light lights[MAX_LIGHTS]; -uniform vec3 cameraPos; -uniform int disableLighting; - - -void main() { - // projection * view * model * position - outPosition = inPosition; - outColor = inColor; - outNormal= normalize(transpose(inverse(mat3(model))) * inNormal); - outUV = inUV; - outTextureID = inTextureID; - outHasTexture = hasTexture; - outLights = lights; - outTotalLights = totalLights; - outCameraPos = cameraPos; - outDisableLighting = disableLighting; - - outFragPos = vec3(model * vec4(inPosition, 1.0)); - - gl_Position = projection * view * model * vec4(inPosition, 1.0); -} diff --git a/shaders/vertex/render_screen.glsl b/shaders/vertex/deferred_lighting.glsl similarity index 59% rename from shaders/vertex/render_screen.glsl rename to shaders/vertex/deferred_lighting.glsl index d032ce4..e8adf57 100644 --- a/shaders/vertex/render_screen.glsl +++ b/shaders/vertex/deferred_lighting.glsl @@ -1,10 +1,17 @@ #version 330 core +@include "light_struct" + layout (location = 0) in vec3 inPosition; layout (location = 1) in vec2 inTexCoords; +uniform sampler2D diffuse, position, texcoord, normal, depth; +uniform Light light; + out vec2 outTexCoords; +flat out Light outLight; void main() { - gl_Position = vec4(inPosition.x, inPosition.y, inPosition.z, 1.0); + gl_Position = vec4(inPosition.x, inPosition.y, inPosition.z, 1.0); outTexCoords = inTexCoords; -} \ No newline at end of file + outLight = light; +} \ No newline at end of file diff --git a/shaders/vertex/g_buffer.glsl b/shaders/vertex/g_buffer.glsl new file mode 100644 index 0000000..d5551ca --- /dev/null +++ b/shaders/vertex/g_buffer.glsl @@ -0,0 +1,28 @@ +# version 330 core + +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inColor; +layout(location = 2) in vec3 inNormal; +layout(location = 3) in vec3 inUV; + +uniform mat4 projection, view, model; +uniform int hasTexture; +uniform vec3 cameraPos; + +out vec3 outPosition, outColor, outNormal, outUV; +out vec3 outFragPos, outViewPos, outCameraPos; +flat out int outHasTexture; + +void main() { + // projection * view * model * position + outPosition = inPosition; + outColor = inColor; + outNormal= normalize(transpose(inverse(mat3(model))) * inNormal); + outUV = inUV; + outHasTexture = hasTexture; + outCameraPos = cameraPos; + + outFragPos = vec3(model * vec4(inPosition, 1.0)); + + gl_Position = projection * view * model * vec4(inPosition, 1.0); +}