diff --git a/src/rlgl.h b/src/rlgl.h index 76b765e2e..e8db37b01 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -575,14 +575,16 @@ typedef enum { // Framebuffer texture attachment type typedef enum { - RL_ATTACHMENT_CUBEMAP_POSITIVE_X = 0, // Framebuffer texture attachment type: cubemap, +X side - RL_ATTACHMENT_CUBEMAP_NEGATIVE_X = 1, // Framebuffer texture attachment type: cubemap, -X side - RL_ATTACHMENT_CUBEMAP_POSITIVE_Y = 2, // Framebuffer texture attachment type: cubemap, +Y side - RL_ATTACHMENT_CUBEMAP_NEGATIVE_Y = 3, // Framebuffer texture attachment type: cubemap, -Y side - RL_ATTACHMENT_CUBEMAP_POSITIVE_Z = 4, // Framebuffer texture attachment type: cubemap, +Z side - RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z = 5, // Framebuffer texture attachment type: cubemap, -Z side - RL_ATTACHMENT_TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d - RL_ATTACHMENT_RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer + RL_ATTACHMENT_CUBEMAP_POSITIVE_X = 0, // Framebuffer texture attachment type: cubemap, +X side + RL_ATTACHMENT_CUBEMAP_NEGATIVE_X = 1, // Framebuffer texture attachment type: cubemap, -X side + RL_ATTACHMENT_CUBEMAP_POSITIVE_Y = 2, // Framebuffer texture attachment type: cubemap, +Y side + RL_ATTACHMENT_CUBEMAP_NEGATIVE_Y = 3, // Framebuffer texture attachment type: cubemap, -Y side + RL_ATTACHMENT_CUBEMAP_POSITIVE_Z = 4, // Framebuffer texture attachment type: cubemap, +Z side + RL_ATTACHMENT_CUBEMAP_NEGATIVE_Z = 5, // Framebuffer texture attachment type: cubemap, -Z side + RL_ATTACHMENT_TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d + RL_ATTACHMENT_RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer + RL_ATTACHMENT_TEXTURE2D_MULTISAMPLE = 300, // Framebuffer texture attachment type: texture2d, multisampled + RL_ATTACHMENT_RENDERBUFFER_MULTISAMPLE = 400 // Framebuffer texture attachment type: renderbuffer, multisampled } rlFramebufferAttachTextureType; // Face culling mode @@ -754,6 +756,8 @@ RLAPI void rlDrawVertexArrayElementsInstanced(int offset, int count, const void RLAPI unsigned int rlLoadTexture(const void *data, int width, int height, int format, int mipmapCount); // Load texture data RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo) RLAPI unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mipmapCount); // Load texture cubemap data +RLAPI unsigned int rlLoadTextureMultisampled(int width, int height, int format, int samples); // Load multisample texture +RLAPI unsigned int rlLoadTextureDepthMultisampled(int width, int height, int samples, bool useRenderBuffer); // Load multisample depth texture/renderbuffer RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update texture with new data on GPU RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats RLAPI const char *rlGetPixelFormatName(unsigned int format); // Get name string for pixel format @@ -770,6 +774,7 @@ RLAPI void rlUnloadFramebuffer(unsigned int id); // Del // WARNING: Copy and resize framebuffer functionality only defined for software backend RLAPI void rlCopyFramebuffer(int x, int y, int width, int height, int format, void *pixels); // Copy framebuffer pixel data to internal buffer RLAPI void rlResizeFramebuffer(int width, int height); // Resize internal framebuffer +RLAPI void rlDownsampleFramebuffer(unsigned int fboId, unsigned int destFbo, int width, int height); // Downsample framebuffer with multisample attachments // Shaders management RLAPI unsigned int rlLoadShader(const char *code, int type); // Load (compile) shader and return shader id (type: RL_VERTEX_SHADER, RL_FRAGMENT_SHADER, RL_COMPUTE_SHADER) @@ -3597,6 +3602,101 @@ unsigned int rlLoadTextureCubemap(const void *data, int size, int format, int mi return id; } +// Load multisample texture (to attach to fbo) +unsigned int rlLoadMultisampleTexture(int width, int height, int format, int samples) +{ + unsigned int id = 0; + + if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return id; } + +#if defined(GRAPHICS_API_OPENGL_11) + TRACELOG(RL_LOG_WARNING, "GL: OpenGL 1.1 does not support multisample textures"); + return id; +#elif !defined(GRAPHICS_API_OPENGL_ES3) && defined(GRAPHICS_API_OPENGL_ES2) + TRACELOG(RL_LOG_WARNING, "GL: OpenGL ES 2.0 does not support multisample textures"); + return id; +#endif // GRAPHICS_API_OPENGL_11 + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); // Free old binding + + glGenTextures(1, &id); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, id); + + unsigned int glInternalFormat, glFormat, glType; + rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); + + if (glInternalFormat != 0) + { + #if defined(GRAPHICS_API_OPENGL_43) || defined(GRAPHICS_API_OPENGL_ES3) + glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, glInternalFormat, width, height, 1); + #elif defined(GRAPHICS_API_OPENGL_33) + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, glInternalFormat, width, height, 1); + #endif + } + + if (id > 0) TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Multisample texture loaded successfully (%ix%i | %s)", id, width, height, rlGetPixelFormatName(format)); + else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to load multisample texture"); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + return id; +} + +// Load multisample depth texture/renderbuffer (to attach to fbo) +unsigned int rlLoadMultisampleTextureDepth(int width, int height, int samples, bool useRenderBuffer) +{ + unsigned int id = 0; + if (!isGpuReady) { TRACELOG(RL_LOG_WARNING, "GL: GPU is not ready to load data, trying to load before InitWindow()?"); return id; } + +#if defined(GRAPHICS_API_OPENGL_11) + TRACELOG(RL_LOG_WARNING, "GL: OpenGL 1.1 does not support multisample depth textures"); + return id; +#elif !defined(GRAPHICS_API_OPENGL_ES3) && defined(GRAPHICS_API_OPENGL_ES2) + TRACELOG(RL_LOG_WARNING, "GL: OpenGL ES 2.0 does not support multisample depth textures"); + return id; +#endif // GRAPHICS_API_OPENGL_11 + + if (!RLGL.ExtSupported.texDepth) useRenderBuffer = true; + unsigned int glInternalFormat = GL_DEPTH_COMPONENT; + +#if defined(GRAPHICS_API_OPENGL_ES3) + if (RLGL.ExtSupported.maxDepthBits == 24) glInternalFormat = GL_DEPTH_COMPONENT24; + else glInternalFormat = GL_DEPTH_COMPONENT16; +#endif + + if (!useRenderBuffer && RLGL.ExtSupported.texDepth) + { + glGenTextures(1, &id); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, id); + + #if defined(GRAPHICS_API_OPENGL_43) || defined(GRAPHICS_API_OPENGL_ES3) + glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, glInternalFormat, width, height, 1); + #elif defined(GRAPHICS_API_OPENGL_33) + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, glInternalFormat, width, height, 1); + #endif + + glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + + TRACELOG(RL_LOG_INFO, "TEXTURE: Multisample depth texture loaded successfully"); + } + else + { + glGenRenderbuffers(1, &id); + glBindRenderbuffer(GL_RENDERBUFFER, id); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, glInternalFormat, width, height); + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Multisample depth renderbuffer loaded successfully (%i bits)", id, (RLGL.ExtSupported.maxDepthBits >= 24)? RLGL.ExtSupported.maxDepthBits : 16); + } + + return id; +} + // Update already loaded texture in GPU with new data // WARNING: Not possible to know safely if internal texture format is the expected one... void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data) @@ -3808,6 +3908,18 @@ void rlResizeFramebuffer(int width, int height) #endif } +// Copy the contents of MSAA framebuffer to non-MSAA framebuffer +void rlDownsampleFramebuffer(unsigned int fboId, unsigned int destFbo, int width, int height) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES3) + glBindFramebuffer(GL_READ_FRAMEBUFFER, fboId); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destFbo); + + glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +#endif +} + // Read screen pixel data (color buffer) unsigned char *rlReadScreenPixels(int width, int height) { @@ -3869,32 +3981,17 @@ void rlFramebufferAttach(unsigned int id, unsigned int texId, int attachType, in #if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_SOFTWARE)) glBindFramebuffer(GL_FRAMEBUFFER, id); - switch (attachType) - { - case RL_ATTACHMENT_COLOR_CHANNEL0: - case RL_ATTACHMENT_COLOR_CHANNEL1: - case RL_ATTACHMENT_COLOR_CHANNEL2: - case RL_ATTACHMENT_COLOR_CHANNEL3: - case RL_ATTACHMENT_COLOR_CHANNEL4: - case RL_ATTACHMENT_COLOR_CHANNEL5: - case RL_ATTACHMENT_COLOR_CHANNEL6: - case RL_ATTACHMENT_COLOR_CHANNEL7: - { - if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_2D, texId, mipLevel); - else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_RENDERBUFFER, texId); - else if (texType >= RL_ATTACHMENT_CUBEMAP_POSITIVE_X) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachType, GL_TEXTURE_CUBE_MAP_POSITIVE_X + texType, texId, mipLevel); - } break; - case RL_ATTACHMENT_DEPTH: - { - if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel); - else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, texId); - } break; - case RL_ATTACHMENT_STENCIL: - { - if (texType == RL_ATTACHMENT_TEXTURE2D) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId, mipLevel); - else if (texType == RL_ATTACHMENT_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, texId); - } break; - default: break; + int attach = 0; + if(attachType <= RL_ATTACHMENT_COLOR_CHANNEL7) attach = GL_COLOR_ATTACHMENT0 + attachType; + else if(attachType == RL_ATTACHMENT_DEPTH) attach = GL_DEPTH_ATTACHMENT; + else if(attachType == RL_ATTACHMENT_STENCIL) attach = GL_STENCIL_ATTACHMENT; + + switch(texType) { + case RL_ATTACHMENT_RENDERBUFFER_MULTISAMPLE: + case RL_ATTACHMENT_RENDERBUFFER: glFramebufferRenderbuffer(GL_FRAMEBUFFER, attach, GL_RENDERBUFFER, texId); break; + case RL_ATTACHMENT_TEXTURE2D: glFramebufferTexture2D(GL_FRAMEBUFFER, attach, GL_TEXTURE_2D, texId, mipLevel); break; + case RL_ATTACHMENT_TEXTURE2D_MULTISAMPLE: glFramebufferTexture2D(GL_FRAMEBUFFER, attach, GL_TEXTURE_2D_MULTISAMPLE, texId, mipLevel); break; + default: if(attachType <= RL_ATTACHMENT_COLOR_CHANNEL7) glFramebufferTexture2D(GL_FRAMEBUFFER, attach, GL_TEXTURE_CUBE_MAP_POSITIVE_X + texType, texId, mipLevel); } glBindFramebuffer(GL_FRAMEBUFFER, 0);