121 lines
4.4 KiB
C
121 lines
4.4 KiB
C
#include "render_impl.h"
|
|
|
|
typedef struct s_gbuffer{
|
|
//framebuffer
|
|
unsigned int framebuffer;
|
|
unsigned int depthRenderbuffer;
|
|
//texture
|
|
unsigned int positionTexture;
|
|
unsigned int normalTexture;
|
|
unsigned int albedoSpecTexture;
|
|
unsigned int zTexture;
|
|
//format
|
|
unsigned int width;
|
|
unsigned int height;
|
|
} gbuffer_t;
|
|
|
|
gbuffer_t haven_gbuffer_init(int width, int height) {
|
|
gbuffer_t buffer = {0};
|
|
buffer.height = height;
|
|
buffer.width = width;
|
|
|
|
buffer.framebuffer = rlLoadFramebuffer();
|
|
if (!buffer.framebuffer) {
|
|
TraceLog(LOG_WARNING, "failed to create framebuffer");
|
|
exit(1);
|
|
}
|
|
|
|
rlEnableFramebuffer(buffer.framebuffer);
|
|
buffer.positionTexture = rlLoadTexture(NULL, width,height, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1);
|
|
buffer.normalTexture = rlLoadTexture(NULL, width,height, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1);
|
|
buffer.albedoSpecTexture = rlLoadTexture(NULL, width,height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
|
|
buffer.zTexture = rlLoadTexture(NULL, width,height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
|
|
buffer.depthRenderbuffer = rlLoadTextureDepth(width, height, true);
|
|
rlActiveDrawBuffers(4);
|
|
|
|
rlFramebufferAttach(buffer.framebuffer, buffer.positionTexture, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0);
|
|
rlFramebufferAttach(buffer.framebuffer, buffer.normalTexture, RL_ATTACHMENT_COLOR_CHANNEL1, RL_ATTACHMENT_TEXTURE2D, 0);
|
|
rlFramebufferAttach(buffer.framebuffer, buffer.albedoSpecTexture, RL_ATTACHMENT_COLOR_CHANNEL2, RL_ATTACHMENT_TEXTURE2D, 0);
|
|
rlFramebufferAttach(buffer.framebuffer, buffer.zTexture, RL_ATTACHMENT_COLOR_CHANNEL3, RL_ATTACHMENT_TEXTURE2D, 0);
|
|
rlFramebufferAttach(buffer.framebuffer, buffer.depthRenderbuffer, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0);
|
|
|
|
|
|
if (!rlFramebufferComplete(buffer.framebuffer)) {
|
|
TraceLog(LOG_WARNING, "Framebuffer is not complete");
|
|
exit(1);
|
|
}
|
|
|
|
return (buffer);
|
|
}
|
|
|
|
void haven_deferred_set_loc(Shader shader) {
|
|
rlEnableShader(shader.id);
|
|
int tex_unit_posistion = 0;
|
|
int tex_unit_normal = 1;
|
|
int tex_unit_albedospec = 2;
|
|
int tex_unit_z = 3;
|
|
SetShaderValue(shader, rlGetLocationUniform(shader.id, "gPosition"), &tex_unit_posistion, RL_SHADER_UNIFORM_SAMPLER2D);
|
|
SetShaderValue(shader, rlGetLocationUniform(shader.id, "gNormal"), &tex_unit_normal, RL_SHADER_UNIFORM_SAMPLER2D);
|
|
SetShaderValue(shader, rlGetLocationUniform(shader.id, "gAlbedoSpec"), &tex_unit_albedospec, RL_SHADER_UNIFORM_SAMPLER2D);
|
|
SetShaderValue(shader, rlGetLocationUniform(shader.id, "gZ"), &tex_unit_z, RL_SHADER_UNIFORM_SAMPLER2D);
|
|
rlDisableShader();
|
|
}
|
|
|
|
void haven_gbuffer_start_draw(const gbuffer_t gbuffer, const Camera3D camera, const Shader gbuffershader) {
|
|
rlEnableFramebuffer(gbuffer.framebuffer);
|
|
rlClearColor(0, 0, 0, 0);
|
|
rlClearScreenBuffers();
|
|
|
|
rlDisableColorBlend();
|
|
BeginMode3D(camera);
|
|
rlEnableShader(gbuffershader.id);
|
|
}
|
|
|
|
void haven_gbuffer_end_draw() {
|
|
rlDisableShader();
|
|
EndMode3D();
|
|
|
|
rlEnableColorBlend();
|
|
rlDisableFramebuffer();
|
|
rlClearScreenBuffers();
|
|
}
|
|
|
|
void haven_gbuffer_rendering(const gbuffer_t gbuffer, const Camera3D camera, const Shader deferredshader) {
|
|
BeginMode3D(camera); {
|
|
rlDisableColorBlend();
|
|
rlEnableShader(deferredshader.id); {
|
|
|
|
// Bind our g-buffer textures
|
|
// We are binding them to locations that we earlier set in sampler2D uniforms `gPosition`, `gNormal`,
|
|
// `gAlbedoSpec` and gZ
|
|
rlActiveTextureSlot(0);
|
|
rlEnableTexture(gbuffer.positionTexture);
|
|
rlActiveTextureSlot(1);
|
|
rlEnableTexture(gbuffer.normalTexture);
|
|
rlActiveTextureSlot(2);
|
|
rlEnableTexture(gbuffer.albedoSpecTexture);
|
|
rlActiveTextureSlot(3);
|
|
rlEnableTexture(gbuffer.zTexture);
|
|
|
|
// 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.
|
|
rlBindFramebuffer(RL_READ_FRAMEBUFFER, gbuffer.framebuffer);
|
|
rlBindFramebuffer(RL_DRAW_FRAMEBUFFER, 0);
|
|
rlBlitFramebuffer(0, 0, gbuffer.width, gbuffer.height, 0, 0, gbuffer.width, gbuffer.height, 0x00000100);//0x00000100 -> GL_DEPTH_BUFFER_BIT
|
|
rlDisableFramebuffer();
|
|
}
|
|
|
|
void haven_gbuffer_texture_render(const unsigned int texture_id, const unsigned int width, const unsigned int height) {
|
|
DrawTextureRec((Texture2D){
|
|
.id = texture_id,
|
|
.width = width,
|
|
.height = -height,
|
|
}, (Rectangle) {0, 0, width, -height}, Vector2Zero(), RAYWHITE);
|
|
} |