From 7a4f04f1df6896a4978ba302ea3fc79b6e7dd1f7 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Mon, 16 Aug 2021 17:12:23 -0400 Subject: graphics: Add basic image based ambient lighting. --- chickadee/graphics/mesh.scm | 25 ++++++++++++++----------- chickadee/graphics/model.scm | 11 +++++------ data/shaders/pbr-frag.glsl | 14 +++++++++----- data/shaders/phong-frag.glsl | 11 ++++++++--- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/chickadee/graphics/mesh.scm b/chickadee/graphics/mesh.scm index ab7ad45..44c670e 100644 --- a/chickadee/graphics/mesh.scm +++ b/chickadee/graphics/mesh.scm @@ -33,6 +33,7 @@ #:use-module (chickadee graphics light) #:use-module (chickadee graphics polygon) #:use-module (chickadee graphics shader) + #:use-module (chickadee graphics skybox) #:use-module (chickadee graphics stencil) #:use-module (chickadee graphics texture) #:use-module (chickadee utils) @@ -123,24 +124,26 @@ (define %camera-position (vec3 0.0 0.0 0.0)) (define (material-apply material vertex-array model-matrix view-matrix - camera-position ambient-light light-vector) + camera-position skybox light-vector) (with-graphics-state ((g:blend-mode (material-blend-mode material)) (g:cull-face-mode (material-cull-face-mode material)) (g:depth-test (material-depth-test material)) (g:multisample? (material-multisample? material)) (g:polygon-mode (material-polygon-mode material)) (g:stencil-test (material-stencil-test material)) - (g:texture-0 (material-texture-0 material)) - (g:texture-1 (material-texture-1 material)) - (g:texture-2 (material-texture-2 material)) - (g:texture-3 (material-texture-3 material)) - (g:texture-4 (material-texture-4 material))) + (g:texture-0 (if skybox + (skybox-cube-map skybox) + null-texture)) + (g:texture-1 (material-texture-0 material)) + (g:texture-2 (material-texture-1 material)) + (g:texture-3 (material-texture-2 material)) + (g:texture-4 (material-texture-3 material)) + (g:texture-5 (material-texture-4 material))) (shader-apply (material-shader material) vertex-array #:model model-matrix #:view view-matrix #:projection (current-projection) #:camera-position camera-position - #:ambient-light ambient-light #:lights light-vector #:material (material-properties material)))) @@ -159,13 +162,13 @@ (material primitive-material)) (define (draw-primitive primitive model-matrix view-matrix camera-position - ambient-light light-vector) + skybox light-vector) (material-apply (primitive-material primitive) (primitive-vertex-array primitive) model-matrix view-matrix camera-position - ambient-light + skybox light-vector)) @@ -190,7 +193,7 @@ (define* (draw-mesh mesh #:key (model-matrix %identity-matrix) (view-matrix %identity-matrix) (camera-position %origin) - (ambient-light black) + skybox (lights '())) ;; Populate light vector to pass on to shader. (let ((light-vector (mesh-light-vector mesh))) @@ -206,7 +209,7 @@ (loop (+ i 1) rest))))) (for-each (lambda (primitive) (draw-primitive primitive model-matrix view-matrix camera-position - ambient-light light-vector)) + skybox light-vector)) (mesh-primitives mesh)))) diff --git a/chickadee/graphics/model.scm b/chickadee/graphics/model.scm index 8b7cbda..839ddd1 100644 --- a/chickadee/graphics/model.scm +++ b/chickadee/graphics/model.scm @@ -114,11 +114,10 @@ (children '())) (%make-model-node name mesh matrix world-matrix children)) -(define (draw-model-node node state view-matrix camera-position ambient-light - lights) +(define (draw-model-node node state view-matrix camera-position skybox lights) (for-each (lambda (child) (draw-model-node child state view-matrix camera-position - ambient-light lights)) + skybox lights)) (model-node-children node)) (let ((mesh (model-node-mesh node))) (when mesh @@ -128,7 +127,7 @@ #:model-matrix (render-state-world-model-matrix state) #:view-matrix view-matrix #:camera-position camera-position - #:ambient-light ambient-light + #:skybox skybox #:lights lights)))) @@ -152,7 +151,7 @@ (define %depth-test (make-depth-test)) (define* (draw-model model model-matrix view-matrix camera-position #:key - (ambient-light black) + skybox (lights '())) (with-graphics-state ((g:depth-test %depth-test) (g:multisample? #t)) @@ -161,7 +160,7 @@ (render-state-model-matrix-mult! state model-matrix) ;; TODO: Support drawing non-default scenes. (draw-model-node (model-default-scene model) state view-matrix - camera-position ambient-light lights)))) + camera-position skybox lights)))) ;;; diff --git a/data/shaders/pbr-frag.glsl b/data/shaders/pbr-frag.glsl index c474981..fff725a 100644 --- a/data/shaders/pbr-frag.glsl +++ b/data/shaders/pbr-frag.glsl @@ -47,9 +47,9 @@ out vec4 fragColor; uniform Material material; uniform Light lights[MAX_LIGHTS]; -uniform vec4 ambientLight; uniform bool vertexColored; uniform vec3 cameraPosition; +uniform samplerCube skybox; uniform sampler2D baseColorTexture; uniform sampler2D metallicRoughnessTexture; uniform sampler2D normalTexture; @@ -244,6 +244,7 @@ void main(void) { float metallic = materialMetallic(); float roughness = materialRoughness(); vec3 normal = materialNormal(); + vec3 reflection = reflect(-viewDirection, normal); // The "raw" albedo has an alpha channel which we need to preserve // so that we can apply the desired alpha blending method at the // end, but it is completely ignored for lighting calculations. @@ -356,11 +357,14 @@ void main(void) { // The emissive texture says which fragments emit light. We simply // add this light value to the color accumulator. color += materialEmissive(); - // Apply simple ambient lighting. The affect of the ambient light - // is dampened by the ambient occlusion factor. + // Apply image based ambient lighting. The affect of the ambient + // light is dampened by the ambient occlusion factor. // - // TODO: Use image based lighting. - color += ambientLight.rgb * albedo * ambientOcclusion; + // TODO: Use fancy PBR equations instead of these basic ones. + float fresnel = pow(1.0 - clamp(dot(viewDirection, normal), 0.0, 1.0), 5); + vec3 ambientDiffuse = textureCube(skybox, normal).rgb; + vec3 ambientSpecular = textureLod(skybox, reflection, roughness * 7.0).rgb; + color += (ambientDiffuse * albedo + ambientSpecular * fresnel) * ambientOcclusion; // Apply Reinhard tone mapping to convert our high dynamic range // color value to low dynamic range. All of the lighting // calculations stacked on top of each other is likely to create diff --git a/data/shaders/phong-frag.glsl b/data/shaders/phong-frag.glsl index 0beb75b..9c86c83 100644 --- a/data/shaders/phong-frag.glsl +++ b/data/shaders/phong-frag.glsl @@ -32,6 +32,7 @@ in vec2 fragTex; out vec4 fragColor; #endif +uniform samplerCube skybox; uniform sampler2D ambientMap; uniform sampler2D diffuseMap; uniform sampler2D specularMap; @@ -39,7 +40,6 @@ uniform sampler2D normalMap; uniform Material material; uniform Light lights[MAX_LIGHTS]; uniform vec3 cameraPosition; -uniform vec4 ambientLight; const float GAMMA = 2.2; @@ -135,6 +135,7 @@ void main() { vec3 diffuseColor = materialDiffuse(); vec3 specularColor = materialSpecular(); vec3 normal = materialNormal(); + vec3 reflection = reflect(-viewDir, normal); vec3 color = vec3(0.0); // Apply direct lighting. @@ -155,8 +156,12 @@ void main() { color += diffuseLight * diffuseColor + specularLight * specularColor; } - // Apply ambient lighting. - vec3 ambientColor = diffuseColor * ambientLight.rgb * ambientOcclusion; + // Apply image based ambient lighting. + float fresnel = pow(1.0 - clamp(dot(viewDir, normal), 0.0, 1.0), 5); + float roughness = 1.0 - (material.shininess / 1000.0); + vec3 ambientDiffuse = textureCube(skybox, normal).rgb * diffuseColor; + vec3 ambientSpecular = textureLod(skybox, reflection, roughness * 7.0).rgb * fresnel; + vec3 ambientColor = (ambientDiffuse + ambientSpecular) * ambientOcclusion; color += ambientColor; // Apply gamma correction and HDR tone mapping to get the final -- cgit v1.2.3