examples/shaders: Add an example for deferred shading (#3496)
* add example for deferred rendering/shading * adapt convention --------- Co-authored-by: 27justin <me@justin.cx>
This commit is contained in:
parent
de7beef05d
commit
3645244f9f
9 changed files with 442 additions and 6 deletions
|
@ -562,7 +562,8 @@ SHADERS = \
|
|||
shaders/shaders_mesh_instancing \
|
||||
shaders/shaders_multi_sample2d \
|
||||
shaders/shaders_write_depth \
|
||||
shaders/shaders_hybrid_render
|
||||
shaders/shaders_hybrid_render \
|
||||
shaders/shaders_deferred_render
|
||||
|
||||
AUDIO = \
|
||||
audio/audio_module_playing \
|
||||
|
|
|
@ -468,7 +468,8 @@ SHADERS = \
|
|||
shaders/shaders_mesh_instancing \
|
||||
shaders/shaders_multi_sample2d \
|
||||
shaders/shaders_write_depth \
|
||||
shaders/shaders_hybrid_render
|
||||
shaders/shaders_hybrid_render \
|
||||
shaders/shaders_deferred_render
|
||||
|
||||
AUDIO = \
|
||||
audio/audio_module_playing \
|
||||
|
|
|
@ -176,6 +176,7 @@ Examples using raylib shaders functionality, including shaders loading, paramete
|
|||
| 114 | [shaders_mesh_instancing](shaders/shaders_mesh_instancing.c) | <img src="shaders/shaders_mesh_instancing.png" alt="shaders_mesh_instancing" width="80"> | ⭐️⭐️⭐️⭐️ | 3.7 | **4.2** | [seanpringle](https://github.com/seanpringle) |
|
||||
| 115 | [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | <img src="shaders/shaders_multi_sample2d.png" alt="shaders_multi_sample2d" width="80"> | ⭐️⭐️☆☆ | 3.5 | 3.5 | [Ray](https://github.com/raysan5) |
|
||||
| 116 | [shaders_spotlight](shaders/shaders_spotlight.c) | <img src="shaders/shaders_spotlight.png" alt="shaders_spotlight" width="80"> | ⭐️⭐️☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/codifies) |
|
||||
| 117 | [shaders_deferred_render](shaders/shaders_deferred_render.c) | <img src="shaders/shaders_deferred_render.png" alt="shaders_deferred_render" width="80"> | ⭐️⭐️⭐️⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) |
|
||||
|
||||
### category: audio
|
||||
|
||||
|
@ -183,10 +184,10 @@ Examples using raylib audio functionality, including sound/music loading and pla
|
|||
|
||||
| ## | example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|
||||
|----|----------|--------|:-------------------:|:------------------:|:------------------:|:----------|
|
||||
| 117 | [audio_module_playing](audio/audio_module_playing.c) | <img src="audio/audio_module_playing.png" alt="audio_module_playing" width="80"> | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) |
|
||||
| 118 | [audio_music_stream](audio/audio_music_stream.c) | <img src="audio/audio_music_stream.png" alt="audio_music_stream" width="80"> | ⭐️☆☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) |
|
||||
| 119 | [audio_raw_stream](audio/audio_raw_stream.c) | <img src="audio/audio_raw_stream.png" alt="audio_raw_stream" width="80"> | ⭐️⭐️⭐️☆ | 1.6 | **4.2** | [Ray](https://github.com/raysan5) |
|
||||
| 120 | [audio_sound_loading](audio/audio_sound_loading.c) | <img src="audio/audio_sound_loading.png" alt="audio_sound_loading" width="80"> | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) |
|
||||
| 118 | [audio_module_playing](audio/audio_module_playing.c) | <img src="audio/audio_module_playing.png" alt="audio_module_playing" width="80"> | ⭐️☆☆☆ | 1.5 | 3.5 | [Ray](https://github.com/raysan5) |
|
||||
| 119 | [audio_music_stream](audio/audio_music_stream.c) | <img src="audio/audio_music_stream.png" alt="audio_music_stream" width="80"> | ⭐️☆☆☆ | 1.3 | **4.2** | [Ray](https://github.com/raysan5) |
|
||||
| 120 | [audio_raw_stream](audio/audio_raw_stream.c) | <img src="audio/audio_raw_stream.png" alt="audio_raw_stream" width="80"> | ⭐️⭐️⭐️☆ | 1.6 | **4.2** | [Ray](https://github.com/raysan5) |
|
||||
| 121 | [audio_sound_loading](audio/audio_sound_loading.c) | <img src="audio/audio_sound_loading.png" alt="audio_sound_loading" width="80"> | ⭐️☆☆☆ | 1.1 | 3.5 | [Ray](https://github.com/raysan5) |
|
||||
|
||||
### category: others
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#version 330 core
|
||||
out vec4 finalColor;
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec2 texCoord2;
|
||||
|
||||
uniform sampler2D gPosition;
|
||||
uniform sampler2D gNormal;
|
||||
uniform sampler2D gAlbedoSpec;
|
||||
|
||||
struct Light {
|
||||
int enabled;
|
||||
int type; // Unused in this demo.
|
||||
vec3 position;
|
||||
vec3 target; // Unused in this demo.
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
const int NR_LIGHTS = 4;
|
||||
uniform Light lights[NR_LIGHTS];
|
||||
uniform vec3 viewPosition;
|
||||
|
||||
const float QUADRATIC = 0.032;
|
||||
const float LINEAR = 0.09;
|
||||
|
||||
void main() {
|
||||
vec3 fragPosition = texture(gPosition, texCoord).rgb;
|
||||
vec3 normal = texture(gNormal, texCoord).rgb;
|
||||
vec3 albedo = texture(gAlbedoSpec, texCoord).rgb;
|
||||
float specular = texture(gAlbedoSpec, texCoord).a;
|
||||
|
||||
vec3 ambient = albedo * vec3(0.1f);
|
||||
vec3 viewDirection = normalize(viewPosition - fragPosition);
|
||||
|
||||
for(int i = 0; i < NR_LIGHTS; ++i)
|
||||
{
|
||||
if(lights[i].enabled == 0) continue;
|
||||
vec3 lightDirection = lights[i].position - fragPosition;
|
||||
vec3 diffuse = max(dot(normal, lightDirection), 0.0) * albedo * lights[i].color.xyz;
|
||||
|
||||
vec3 halfwayDirection = normalize(lightDirection + viewDirection);
|
||||
float spec = pow(max(dot(normal, halfwayDirection), 0.0), 32.0);
|
||||
vec3 specular = specular * spec * lights[i].color.xyz;
|
||||
|
||||
// Attenuation
|
||||
float distance = length(lights[i].position - fragPosition);
|
||||
float attenuation = 1.0 / (1.0 + LINEAR * distance + QUADRATIC * distance * distance);
|
||||
diffuse *= attenuation;
|
||||
specular *= attenuation;
|
||||
ambient += diffuse + specular;
|
||||
}
|
||||
|
||||
finalColor = vec4(ambient, 1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec3 vertexPosition;
|
||||
layout (location = 1) in vec2 vertexTexCoord;
|
||||
|
||||
out vec2 texCoord;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(vertexPosition, 1.0);
|
||||
texCoord = vertexTexCoord;
|
||||
}
|
22
examples/shaders/resources/shaders/glsl330/gbuffer.fs
Normal file
22
examples/shaders/resources/shaders/glsl330/gbuffer.fs
Normal file
|
@ -0,0 +1,22 @@
|
|||
#version 330 core
|
||||
layout (location = 0) out vec3 gPosition;
|
||||
layout (location = 1) out vec3 gNormal;
|
||||
layout (location = 2) out vec4 gAlbedoSpec;
|
||||
|
||||
in vec3 fragPosition;
|
||||
in vec2 fragTexCoord;
|
||||
in vec3 fragNormal;
|
||||
|
||||
uniform sampler2D diffuseTexture;
|
||||
uniform sampler2D specularTexture;
|
||||
|
||||
void main() {
|
||||
// store the fragment position vector in the first gbuffer texture
|
||||
gPosition = fragPosition;
|
||||
// also store the per-fragment normals into the gbuffer
|
||||
gNormal = normalize(fragNormal);
|
||||
// and the diffuse per-fragment color
|
||||
gAlbedoSpec.rgb = texture(diffuseTexture, fragTexCoord).rgb;
|
||||
// store specular intensity in gAlbedoSpec's alpha component
|
||||
gAlbedoSpec.a = texture(specularTexture, fragTexCoord).r;
|
||||
}
|
24
examples/shaders/resources/shaders/glsl330/gbuffer.vs
Normal file
24
examples/shaders/resources/shaders/glsl330/gbuffer.vs
Normal file
|
@ -0,0 +1,24 @@
|
|||
#version 330 core
|
||||
layout (location = 0) in vec3 vertexPosition;
|
||||
layout (location = 1) in vec2 vertexTexCoord;
|
||||
layout (location = 2) in vec3 vertexNormal;
|
||||
|
||||
out vec3 fragPosition;
|
||||
out vec2 fragTexCoord;
|
||||
out vec3 fragNormal;
|
||||
|
||||
uniform mat4 matModel;
|
||||
uniform mat4 matView;
|
||||
uniform mat4 matProjection;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 worldPos = matModel * vec4(vertexPosition, 1.0);
|
||||
fragPosition = worldPos.xyz;
|
||||
fragTexCoord = vertexTexCoord;
|
||||
|
||||
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
|
||||
fragNormal = normalMatrix * vertexNormal;
|
||||
|
||||
gl_Position = matProjection * matView * worldPos;
|
||||
}
|
321
examples/shaders/shaders_deferred_render.c
Normal file
321
examples/shaders/shaders_deferred_render.c
Normal file
|
@ -0,0 +1,321 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - deferred rendering
|
||||
*
|
||||
* NOTE: This example requires raylib OpenGL 3.3 or ES 3 versions.
|
||||
*
|
||||
* Example originally created with raylib 4.5, last time updated with raylib 4.5
|
||||
*
|
||||
* Example contributed by Justin Andreas Lacoste (@27justin) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2023 Justin Andreas Lacoste (@27justin)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <GLES3/gl3.h>
|
||||
|
||||
#include "raylib.h"
|
||||
#include "rlgl.h"
|
||||
|
||||
#include "raymath.h"
|
||||
|
||||
#define RLIGHTS_IMPLEMENTATION
|
||||
#include "rlights.h"
|
||||
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
#define GLSL_VERSION 330
|
||||
#else // PLATFORM_ANDROID, PLATFORM_WEB
|
||||
#define GLSL_VERSION 100
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned int framebuffer;
|
||||
|
||||
unsigned int positionTexture;
|
||||
unsigned int normalTexture;
|
||||
unsigned int albedoSpecTexture;
|
||||
|
||||
unsigned int depthRenderbuffer;
|
||||
} GBuffer;
|
||||
|
||||
int main(void) {
|
||||
// Initialization
|
||||
// -------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - deferred render");
|
||||
|
||||
Camera camera = { 0 };
|
||||
camera.position = (Vector3){ 5.0f, 4.0f, 5.0f }; // Camera position
|
||||
camera.target = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera looking at point
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
|
||||
camera.fovy = 60.0f; // Camera field-of-view Y
|
||||
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
|
||||
|
||||
// Load plane model from a generated mesh
|
||||
Model model = LoadModelFromMesh(GenMeshPlane(10.0f, 10.0f, 3, 3));
|
||||
Model cube = LoadModelFromMesh(GenMeshCube(2.0f, 2.0f, 2.0f));
|
||||
|
||||
// Load geometry buffer (G-buffer) shader and deferred shader
|
||||
Shader gbufferShader = LoadShader("resources/shaders/glsl330/gbuffer.vs",
|
||||
"resources/shaders/glsl330/gbuffer.fs");
|
||||
|
||||
Shader deferredShader = LoadShader("resources/shaders/glsl330/deferred_shading.vs",
|
||||
"resources/shaders/glsl330/deferred_shading.fs");
|
||||
deferredShader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(deferredShader, "viewPosition");
|
||||
|
||||
// Initialize the G-buffer
|
||||
GBuffer gBuffer = { 0 };
|
||||
gBuffer.framebuffer = rlLoadFramebuffer(screenWidth, screenHeight);
|
||||
|
||||
if(!gBuffer.framebuffer)
|
||||
{
|
||||
TraceLog(LOG_WARNING, "Failed to create framebuffer");
|
||||
exit(1);
|
||||
}
|
||||
rlEnableFramebuffer(gBuffer.framebuffer);
|
||||
|
||||
// Since we are storing position and normal data in these textures,
|
||||
// we need to use a floating point format.
|
||||
gBuffer.positionTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32, 1);
|
||||
|
||||
gBuffer.normalTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32, 1);
|
||||
// Albedo (diffuse color) and specular strength can be combined into one texture.
|
||||
// The color in RGB, and the specular strength in the alpha channel.
|
||||
gBuffer.albedoSpecTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
|
||||
|
||||
// Activate the draw buffers for our framebuffer
|
||||
rlActiveDrawBuffers(3);
|
||||
|
||||
// Now we attach our textures to the framebuffer.
|
||||
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.positionTexture, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0);
|
||||
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.normalTexture, RL_ATTACHMENT_COLOR_CHANNEL1, RL_ATTACHMENT_TEXTURE2D, 0);
|
||||
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.albedoSpecTexture, RL_ATTACHMENT_COLOR_CHANNEL2, RL_ATTACHMENT_TEXTURE2D, 0);
|
||||
|
||||
// Finally we attach the depth buffer.
|
||||
gBuffer.depthRenderbuffer = rlLoadTextureDepth(screenWidth, screenHeight, true);
|
||||
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.depthRenderbuffer, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0);
|
||||
|
||||
// Make sure our framebuffer is complete.
|
||||
// NOTE: rlFramebufferComplete() automatically unbinds the framebuffer, so we don't have
|
||||
// to rlDisableFramebuffer() here.
|
||||
if(rlFramebufferComplete(gBuffer.framebuffer) != true)
|
||||
{
|
||||
TraceLog(LOG_WARNING, "Framebuffer is not complete");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Now we initialize the sampler2D uniform's in the deferred shader.
|
||||
// We do this by setting the uniform's value to the color channel slot we earlier
|
||||
// bound our textures to.
|
||||
rlEnableShader(deferredShader.id);
|
||||
|
||||
rlSetUniformSampler(rlGetLocationUniform(deferredShader.id, "gPosition"), 0);
|
||||
rlSetUniformSampler(rlGetLocationUniform(deferredShader.id, "gNormal"), 1);
|
||||
rlSetUniformSampler(rlGetLocationUniform(deferredShader.id, "gAlbedoSpec"), 2);
|
||||
|
||||
rlDisableShader();
|
||||
|
||||
// Assign out lighting shader to model
|
||||
model.materials[0].shader = gbufferShader;
|
||||
cube.materials[0].shader = gbufferShader;
|
||||
|
||||
// Create lights
|
||||
//--------------------------------------------------------------------------------------
|
||||
Light lights[MAX_LIGHTS] = { 0 };
|
||||
lights[0] = CreateLight(LIGHT_POINT, (Vector3){ -2, 1, -2 }, Vector3Zero(), YELLOW, deferredShader);
|
||||
lights[1] = CreateLight(LIGHT_POINT, (Vector3){ 2, 1, 2 }, Vector3Zero(), RED, deferredShader);
|
||||
lights[2] = CreateLight(LIGHT_POINT, (Vector3){ -2, 1, 2 }, Vector3Zero(), GREEN, deferredShader);
|
||||
lights[3] = CreateLight(LIGHT_POINT, (Vector3){ 2, 1, -2 }, Vector3Zero(), BLUE, deferredShader);
|
||||
|
||||
const int MAX_CUBES = 30;
|
||||
const float CUBE_SCALE = 0.25;
|
||||
Vector3 cubePositions[MAX_CUBES];
|
||||
float cubeRotations[MAX_CUBES];
|
||||
for(int i = 0; i < MAX_CUBES; i++)
|
||||
{
|
||||
cubePositions[i] = (Vector3) {
|
||||
.x = (float)(rand() % 10) - 5,
|
||||
.y = (float)(rand() % 5),
|
||||
.z = (float)(rand() % 10) - 5,
|
||||
};
|
||||
cubeRotations[i] = (float)(rand() % 360);
|
||||
}
|
||||
|
||||
enum {
|
||||
POSITION,
|
||||
NORMAL,
|
||||
ALBEDO,
|
||||
DEFERRED_SHADING
|
||||
} activeTexture = DEFERRED_SHADING;
|
||||
|
||||
rlEnableDepthTest();
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera, CAMERA_ORBITAL);
|
||||
|
||||
// Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f })
|
||||
float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z };
|
||||
SetShaderValue(deferredShader, deferredShader.locs[SHADER_LOC_VECTOR_VIEW], cameraPos, SHADER_UNIFORM_VEC3);
|
||||
|
||||
// Check key inputs to enable/disable lights
|
||||
if (IsKeyPressed(KEY_Y)) { lights[0].enabled = !lights[0].enabled; }
|
||||
if (IsKeyPressed(KEY_R)) { lights[1].enabled = !lights[1].enabled; }
|
||||
if (IsKeyPressed(KEY_G)) { lights[2].enabled = !lights[2].enabled; }
|
||||
if (IsKeyPressed(KEY_B)) { lights[3].enabled = !lights[3].enabled; }
|
||||
|
||||
// Check key inputs to switch between G-buffer textures
|
||||
if(IsKeyPressed(KEY_ONE)) activeTexture = POSITION;
|
||||
if(IsKeyPressed(KEY_TWO)) activeTexture = NORMAL;
|
||||
if(IsKeyPressed(KEY_THREE)) activeTexture = ALBEDO;
|
||||
if(IsKeyPressed(KEY_FOUR)) activeTexture = DEFERRED_SHADING;
|
||||
|
||||
|
||||
// Update light values (actually, only enable/disable them)
|
||||
for (int i = 0; i < MAX_LIGHTS; i++) UpdateLightValues(deferredShader, lights[i]);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
// ---------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
// Draw to the geometry buffer by first activating it.
|
||||
rlEnableFramebuffer(gBuffer.framebuffer);
|
||||
rlClearScreenBuffers(); // Clear color & depth buffer
|
||||
|
||||
rlDisableColorBlend();
|
||||
BeginMode3D(camera);
|
||||
// NOTE:
|
||||
// We have to use rlEnableShader here. `BeginShaderMode` or thus `rlSetShader`
|
||||
// will not work, as they won't immediately load the shader program.
|
||||
rlEnableShader(gbufferShader.id);
|
||||
// When drawing a model here, make sure that the material's shaders
|
||||
// are set to the gbuffer shader!
|
||||
DrawModel(model, Vector3Zero(), 1.0f, WHITE);
|
||||
DrawModel(cube, (Vector3) { 0.0, 1.0f, 0.0 }, 1.0f, WHITE);
|
||||
|
||||
for(int i = 0; i < MAX_CUBES; i++)
|
||||
{
|
||||
Vector3 position = cubePositions[i];
|
||||
|
||||
DrawModelEx(cube, position, (Vector3) { 1, 1, 1 }, cubeRotations[i], (Vector3) { CUBE_SCALE, CUBE_SCALE, CUBE_SCALE }, WHITE);
|
||||
}
|
||||
|
||||
rlDisableShader();
|
||||
EndMode3D();
|
||||
rlEnableColorBlend();
|
||||
|
||||
// Go back to the default framebuffer (0) and draw our deferred shading.
|
||||
rlDisableFramebuffer();
|
||||
rlClearScreenBuffers(); // Clear color & depth buffer
|
||||
|
||||
switch(activeTexture)
|
||||
{
|
||||
case DEFERRED_SHADING:
|
||||
BeginMode3D(camera);
|
||||
rlDisableColorBlend();
|
||||
rlEnableShader(deferredShader.id);
|
||||
// Activate our g-buffer textures
|
||||
// These will now be bound to the sampler2D uniforms `gPosition`, `gNormal`,
|
||||
// and `gAlbedoSpec`
|
||||
rlActiveTextureSlot(0);
|
||||
rlEnableTexture(gBuffer.positionTexture);
|
||||
rlActiveTextureSlot(1);
|
||||
rlEnableTexture(gBuffer.normalTexture);
|
||||
rlActiveTextureSlot(2);
|
||||
rlEnableTexture(gBuffer.albedoSpecTexture);
|
||||
|
||||
// Finally, we draw a fullscreen quad to our default framebuffer
|
||||
// This will now be shaded using our deferred shader
|
||||
rlLoadDrawQuad();
|
||||
rlDisableShader();
|
||||
rlEnableColorBlend();
|
||||
EndMode3D();
|
||||
|
||||
// As a last step, we now copy over the depth buffer from our g-buffer to the
|
||||
// default framebuffer.
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gBuffer.framebuffer);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
rlDisableFramebuffer();
|
||||
|
||||
// Since our shader is now done and disabled, we can draw our lights in default
|
||||
// forward rendering
|
||||
BeginMode3D(camera);
|
||||
rlEnableShader(rlGetShaderIdDefault());
|
||||
for(int i = 0; i < MAX_LIGHTS; i++)
|
||||
{
|
||||
if(lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lights[i].color);
|
||||
else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lights[i].color, 0.3f));
|
||||
}
|
||||
rlDisableShader();
|
||||
EndMode3D();
|
||||
DrawText("FINAL RESULT", 10, screenHeight - 30, 20, DARKGREEN);
|
||||
break;
|
||||
case POSITION:
|
||||
DrawTextureRec((Texture2D) {
|
||||
.id = gBuffer.positionTexture,
|
||||
.width = screenWidth,
|
||||
.height = screenHeight,
|
||||
}, (Rectangle) { 0, 0, screenWidth, -screenHeight }, Vector2Zero(), RAYWHITE);
|
||||
DrawText("POSITION TEXTURE", 10, screenHeight - 30, 20, DARKGREEN);
|
||||
break;
|
||||
case NORMAL:
|
||||
DrawTextureRec((Texture2D) {
|
||||
.id = gBuffer.normalTexture,
|
||||
.width = screenWidth,
|
||||
.height = screenHeight,
|
||||
}, (Rectangle) { 0, 0, screenWidth, -screenHeight }, Vector2Zero(), RAYWHITE);
|
||||
DrawText("NORMAL TEXTURE", 10, screenHeight - 30, 20, DARKGREEN);
|
||||
break;
|
||||
|
||||
case ALBEDO:
|
||||
DrawTextureRec((Texture2D) {
|
||||
.id = gBuffer.albedoSpecTexture,
|
||||
.width = screenWidth,
|
||||
.height = screenHeight,
|
||||
}, (Rectangle) { 0, 0, screenWidth, -screenHeight }, Vector2Zero(), RAYWHITE);
|
||||
DrawText("ALBEDO TEXTURE", 10, screenHeight - 30, 20, DARKGREEN);
|
||||
break;
|
||||
}
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
DrawText("Use keys [Y][R][G][B] to toggle lights", 10, 40, 20, DARKGRAY);
|
||||
DrawText("Use keys [1]-[4] to switch between G-buffer textures", 10, 70, 20, DARKGRAY);
|
||||
EndDrawing();
|
||||
// -----------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadModel(model); // Unload the models
|
||||
UnloadModel(cube);
|
||||
|
||||
UnloadShader(deferredShader); // Unload shaders
|
||||
UnloadShader(gbufferShader);
|
||||
|
||||
// Unload geometry buffer and all attached textures
|
||||
rlUnloadFramebuffer(gBuffer.framebuffer);
|
||||
rlUnloadTexture(gBuffer.positionTexture);
|
||||
rlUnloadTexture(gBuffer.normalTexture);
|
||||
rlUnloadTexture(gBuffer.albedoSpecTexture);
|
||||
rlUnloadTexture(gBuffer.depthRenderbuffer);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
BIN
examples/shaders/shaders_deferred_render.png
Normal file
BIN
examples/shaders/shaders_deferred_render.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 89 KiB |
Loading…
Add table
Add a link
Reference in a new issue