mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 17:46:53 -10:00
The memory panel showed no texture bytes and no geometry bytes under OpenGL. Only the depth renderbuffers went into the render target group. All three groups now give a value. Textures: GL_texture_bytes_used holds the bytes of every live texture cache slot. opengl_texture_release_bytes() removes the bytes of a slot at each site that drops its texture data. The bitmap render targets record the bytes of their color texture. Geometry: the unused GL_vertex_data_in global becomes GL_geometry_bytes_used, which counts only vertex and index buffers. This matches the geometry group of the Vulkan backend. gr_opengl_delete_buffer() sets the size of the buffer to 0, because opengl_destroy_all_buffers() calls it a second time for a buffer that the game already deleted. Render targets: three new functions add the scene textures, the post-processing textures, and the shadow map to the group. They sum the bytes at the moment of the call from the textures that exist, thus they need no bookkeeping at the create and delete sites. Co-Authored-By: Claude Opus 5 <[email protected]>
1378 lines
45 KiB
C++
1378 lines
45 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
#include "gropengldraw.h"
|
|
|
|
#include "globalincs/pstypes.h"
|
|
|
|
#include "ShaderProgram.h"
|
|
#include "freespace.h"
|
|
#include "gropengl.h"
|
|
#include "gropengldeferred.h"
|
|
#include "gropenglpostprocessing.h"
|
|
#include "gropenglshader.h"
|
|
#include "gropengltexture.h"
|
|
#include "gropengltnl.h"
|
|
|
|
#include "cmdline/cmdline.h"
|
|
#include "graphics/light.h"
|
|
#include "graphics/matrix.h"
|
|
#include "graphics/paths/PathRenderer.h"
|
|
#include "graphics/util/uniform_structs.h"
|
|
#include "lighting/lighting.h"
|
|
#include "render/3d.h"
|
|
#include "tracing/tracing.h"
|
|
#ifdef USE_OPENGL_ES
|
|
#include "es_compatibility.h"
|
|
#endif
|
|
|
|
GLuint Scene_framebuffer;
|
|
GLuint Scene_framebuffer_ms;
|
|
GLuint Scene_ldr_texture;
|
|
GLuint Scene_color_texture;
|
|
GLuint Scene_position_texture;
|
|
GLuint Scene_normal_texture;
|
|
GLuint Scene_specular_texture;
|
|
GLuint Scene_emissive_texture;
|
|
GLuint Scene_color_texture_ms;
|
|
GLuint Scene_position_texture_ms;
|
|
GLuint Scene_normal_texture_ms;
|
|
GLuint Scene_specular_texture_ms;
|
|
GLuint Scene_emissive_texture_ms;
|
|
GLuint Scene_composite_texture;
|
|
GLuint Scene_luminance_texture;
|
|
GLuint Scene_depth_texture;
|
|
GLuint Scene_depth_texture_ms;
|
|
GLuint Cockpit_depth_texture;
|
|
|
|
GLuint Back_framebuffer;
|
|
GLuint Back_texture;
|
|
GLuint Back_depth_texture;
|
|
|
|
GLuint GammaBlit_framebuffer;
|
|
GLuint GammaBlit_texture;
|
|
|
|
GLuint Distortion_framebuffer = 0;
|
|
GLuint Distortion_texture[2];
|
|
int Distortion_switch = 0;
|
|
|
|
int Scene_texture_initialized;
|
|
|
|
int Scene_texture_width;
|
|
int Scene_texture_height;
|
|
|
|
GLfloat Scene_texture_u_scale = 1.0f;
|
|
GLfloat Scene_texture_v_scale = 1.0f;
|
|
|
|
inline GLenum opengl_primitive_type(primitive_type prim_type)
|
|
{
|
|
switch ( prim_type ) {
|
|
case PRIM_TYPE_POINTS:
|
|
return GL_POINTS;
|
|
case PRIM_TYPE_TRIS:
|
|
return GL_TRIANGLES;
|
|
case PRIM_TYPE_TRISTRIP:
|
|
return GL_TRIANGLE_STRIP;
|
|
case PRIM_TYPE_TRIFAN:
|
|
return GL_TRIANGLE_FAN;
|
|
case PRIM_TYPE_LINES:
|
|
return GL_LINES;
|
|
case PRIM_TYPE_LINESTRIP:
|
|
return GL_LINE_STRIP;
|
|
default:
|
|
return GL_TRIANGLE_FAN;
|
|
}
|
|
}
|
|
|
|
void gr_opengl_sphere(material* material_def, float /*rad*/)
|
|
{
|
|
opengl_tnl_set_material(material_def, true);
|
|
|
|
opengl_draw_sphere();
|
|
}
|
|
|
|
extern int opengl_check_framebuffer();
|
|
void opengl_setup_scene_textures()
|
|
{
|
|
Scene_texture_initialized = 0;
|
|
|
|
if ( Cmdline_no_fbo ) {
|
|
Gr_post_processing_enabled = false;
|
|
Gr_enable_soft_particles = false;
|
|
Gr_framebuffer_effects = {};
|
|
|
|
Scene_ldr_texture = 0;
|
|
Scene_color_texture = 0;
|
|
Scene_depth_texture = 0;
|
|
return;
|
|
}
|
|
|
|
// clamp size, if needed
|
|
Scene_texture_width = gr_screen.max_w;
|
|
Scene_texture_height = gr_screen.max_h;
|
|
|
|
if ( Scene_texture_width > GL_max_renderbuffer_size ) {
|
|
Scene_texture_width = GL_max_renderbuffer_size;
|
|
}
|
|
|
|
if ( Scene_texture_height > GL_max_renderbuffer_size) {
|
|
Scene_texture_height = GL_max_renderbuffer_size;
|
|
}
|
|
|
|
// create framebuffer
|
|
glGenFramebuffers(1, &Scene_framebuffer);
|
|
GL_state.BindFrameBuffer(Scene_framebuffer);
|
|
opengl_set_object_label(GL_FRAMEBUFFER, Scene_framebuffer, "Scene framebuffer");
|
|
|
|
// setup main render texture
|
|
|
|
// setup high dynamic range color texture
|
|
glGenTextures(1, &Scene_color_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Scene_color_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, Scene_texture_width, Scene_texture_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Scene_color_texture, 0);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_color_texture, "Scene color texture");
|
|
|
|
// setup low dynamic range color texture
|
|
glGenTextures(1, &Scene_ldr_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Scene_ldr_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Scene_texture_width, Scene_texture_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_ldr_texture, "Scene LDR texture");
|
|
|
|
// setup position render texture
|
|
glGenTextures(1, &Scene_position_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Scene_position_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, Scene_texture_width, Scene_texture_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_position_texture, "Scene Position texture");
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, Scene_position_texture, 0);
|
|
|
|
// setup normal render texture
|
|
glGenTextures(1, &Scene_normal_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Scene_normal_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, Scene_texture_width, Scene_texture_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_normal_texture, "Scene Normal texture");
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, Scene_normal_texture, 0);
|
|
|
|
// setup specular render texture
|
|
glGenTextures(1, &Scene_specular_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Scene_specular_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Scene_texture_width, Scene_texture_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_specular_texture, "Scene Specular texture");
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, Scene_specular_texture, 0);
|
|
|
|
// setup emissive render texture
|
|
glGenTextures(1, &Scene_emissive_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Scene_emissive_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, Scene_texture_width, Scene_texture_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
glGenerateMipmap(GL_TEXTURE_2D);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_emissive_texture, "Scene Emissive texture");
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, Scene_emissive_texture, 0);
|
|
|
|
// setup compositing render texture
|
|
glGenTextures(1, &Scene_composite_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Scene_composite_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, Scene_texture_width, Scene_texture_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_composite_texture, "Scene Composite texture");
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_2D, Scene_composite_texture, 0);
|
|
|
|
//Set up luminance texture (used as input for FXAA)
|
|
// also used as a light accumulation buffer during the deferred pass
|
|
glGenTextures(1, &Scene_luminance_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Scene_luminance_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, Scene_texture_width, Scene_texture_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_luminance_texture, "Scene Luminance texture");
|
|
|
|
// setup cockpit depth texture
|
|
glGenTextures(1, &Cockpit_depth_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Cockpit_depth_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D,
|
|
0,
|
|
GL_DEPTH24_STENCIL8,
|
|
Scene_texture_width,
|
|
Scene_texture_height,
|
|
0,
|
|
GL_DEPTH_COMPONENT,
|
|
GL_FLOAT,
|
|
nullptr);
|
|
opengl_set_object_label(GL_TEXTURE, Cockpit_depth_texture, "Cockpit depth texture");
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, Cockpit_depth_texture, 0);
|
|
gr_zbuffer_set(GR_ZBUFF_FULL);
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
|
|
// setup main depth texture
|
|
glGenTextures(1, &Scene_depth_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Scene_depth_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D,
|
|
0,
|
|
GL_DEPTH24_STENCIL8,
|
|
Scene_texture_width,
|
|
Scene_texture_height,
|
|
0,
|
|
GL_DEPTH_COMPONENT,
|
|
GL_FLOAT,
|
|
nullptr);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_depth_texture, "Scene depth texture");
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, Scene_depth_texture, 0);
|
|
|
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
|
|
|
if ( opengl_check_framebuffer() ) {
|
|
GL_state.BindFrameBuffer(0);
|
|
glDeleteFramebuffers(1, &Scene_framebuffer);
|
|
Scene_framebuffer = 0;
|
|
|
|
glDeleteTextures(1, &Scene_color_texture);
|
|
Scene_color_texture = 0;
|
|
|
|
glDeleteTextures(1, &Scene_position_texture);
|
|
Scene_position_texture = 0;
|
|
|
|
glDeleteTextures(1, &Scene_normal_texture);
|
|
Scene_normal_texture = 0;
|
|
|
|
glDeleteTextures(1, &Scene_specular_texture);
|
|
Scene_specular_texture = 0;
|
|
|
|
glDeleteTextures(1, &Scene_emissive_texture);
|
|
Scene_emissive_texture = 0;
|
|
|
|
glDeleteTextures(1, &Scene_depth_texture);
|
|
Scene_depth_texture = 0;
|
|
|
|
glDeleteTextures(1, &Scene_luminance_texture);
|
|
Scene_luminance_texture = 0;
|
|
|
|
//glDeleteTextures(1, &Scene_fxaa_output_texture);
|
|
//Scene_fxaa_output_texture = 0;
|
|
|
|
Gr_post_processing_enabled = false;
|
|
Gr_enable_soft_particles = false;
|
|
return;
|
|
}
|
|
|
|
#ifdef USE_OPENGL_ES
|
|
if (Cmdline_msaa_enabled > 0) {
|
|
Cmdline_msaa_enabled = 0;
|
|
Warning(LOCATION, "MSAA is not currently supported under OpenGL ES. Disabling MSAA.");
|
|
}
|
|
#endif
|
|
|
|
if (Cmdline_msaa_enabled > 0) {
|
|
glEnable(GL_MULTISAMPLE);
|
|
|
|
// Make sure our MSAA setting are valid
|
|
int maxSamples;
|
|
glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
|
|
|
|
//Disallow >16 samples due to manual sorting networks in shader
|
|
if (maxSamples > 16)
|
|
maxSamples = 16;
|
|
|
|
if (maxSamples < Cmdline_msaa_enabled) {
|
|
Warning(LOCATION, "Requested MSAA level of %d is not supported. Max MSAA level is %d.", Cmdline_msaa_enabled, maxSamples);
|
|
Cmdline_msaa_enabled = maxSamples;
|
|
}
|
|
else if (Cmdline_msaa_enabled & (Cmdline_msaa_enabled - 1)) {
|
|
int newLevel = 1 << (sizeof(int) * 8 - 2);
|
|
while ((newLevel & Cmdline_msaa_enabled) == 0)
|
|
newLevel = newLevel >> 1;
|
|
Warning(LOCATION, "Requested MSAA level of %d is not a power of 2. Setting to %d.", Cmdline_msaa_enabled, newLevel);
|
|
Cmdline_msaa_enabled = newLevel;
|
|
}
|
|
|
|
// create framebuffer
|
|
glGenFramebuffers(1, &Scene_framebuffer_ms);
|
|
GL_state.BindFrameBuffer(Scene_framebuffer_ms);
|
|
opengl_set_object_label(GL_FRAMEBUFFER, Scene_framebuffer_ms, "Scene framebuffer multisampling");
|
|
|
|
// setup high dynamic range color texture
|
|
glGenTextures(1, &Scene_color_texture_ms);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D_MULTISAMPLE);
|
|
GL_state.Texture.Enable(Scene_color_texture_ms);
|
|
|
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
|
|
Cmdline_msaa_enabled,
|
|
GL_RGBA16F,
|
|
Scene_texture_width,
|
|
Scene_texture_height,
|
|
GL_TRUE);
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
|
GL_COLOR_ATTACHMENT0,
|
|
GL_TEXTURE_2D_MULTISAMPLE,
|
|
Scene_color_texture_ms,
|
|
0);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_color_texture_ms, "Scene color texture multisampling");
|
|
|
|
// setup position render texture
|
|
glGenTextures(1, &Scene_position_texture_ms);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D_MULTISAMPLE);
|
|
GL_state.Texture.Enable(Scene_position_texture_ms);
|
|
|
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
|
|
Cmdline_msaa_enabled,
|
|
GL_RGBA16F,
|
|
Scene_texture_width,
|
|
Scene_texture_height,
|
|
GL_TRUE);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_position_texture_ms, "Scene Position texture multisampling");
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
|
GL_COLOR_ATTACHMENT1,
|
|
GL_TEXTURE_2D_MULTISAMPLE,
|
|
Scene_position_texture_ms,
|
|
0);
|
|
|
|
// setup normal render texture
|
|
glGenTextures(1, &Scene_normal_texture_ms);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D_MULTISAMPLE);
|
|
GL_state.Texture.Enable(Scene_normal_texture_ms);
|
|
|
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
|
|
Cmdline_msaa_enabled,
|
|
GL_RGBA16F,
|
|
Scene_texture_width,
|
|
Scene_texture_height,
|
|
GL_TRUE);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_normal_texture_ms, "Scene Normal texture multisampling");
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
|
GL_COLOR_ATTACHMENT2,
|
|
GL_TEXTURE_2D_MULTISAMPLE,
|
|
Scene_normal_texture_ms,
|
|
0);
|
|
|
|
// setup specular render texture
|
|
glGenTextures(1, &Scene_specular_texture_ms);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D_MULTISAMPLE);
|
|
GL_state.Texture.Enable(Scene_specular_texture_ms);
|
|
|
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
|
|
Cmdline_msaa_enabled,
|
|
GL_RGBA8,
|
|
Scene_texture_width,
|
|
Scene_texture_height,
|
|
GL_TRUE);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_specular_texture_ms, "Scene Specular texture multisample");
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
|
GL_COLOR_ATTACHMENT3,
|
|
GL_TEXTURE_2D_MULTISAMPLE,
|
|
Scene_specular_texture_ms,
|
|
0);
|
|
|
|
// setup emissive render texture
|
|
glGenTextures(1, &Scene_emissive_texture_ms);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D_MULTISAMPLE);
|
|
GL_state.Texture.Enable(Scene_emissive_texture_ms);
|
|
|
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
|
|
Cmdline_msaa_enabled,
|
|
GL_RGBA16F,
|
|
Scene_texture_width,
|
|
Scene_texture_height,
|
|
GL_TRUE);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_emissive_texture_ms, "Scene Emissive texture multisample");
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
|
GL_COLOR_ATTACHMENT4,
|
|
GL_TEXTURE_2D_MULTISAMPLE,
|
|
Scene_emissive_texture_ms,
|
|
0);
|
|
|
|
// setup main depth texture
|
|
glGenTextures(1, &Scene_depth_texture_ms);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D_MULTISAMPLE);
|
|
GL_state.Texture.Enable(Scene_depth_texture_ms);
|
|
|
|
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
|
|
Cmdline_msaa_enabled,
|
|
GL_DEPTH24_STENCIL8,
|
|
Scene_texture_width,
|
|
Scene_texture_height,
|
|
GL_TRUE);
|
|
opengl_set_object_label(GL_TEXTURE, Scene_depth_texture_ms, "Scene depth texture multisample");
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER,
|
|
GL_DEPTH_STENCIL_ATTACHMENT,
|
|
GL_TEXTURE_2D_MULTISAMPLE,
|
|
Scene_depth_texture_ms,
|
|
0);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
}
|
|
|
|
if (Cmdline_window_res) {
|
|
//Gen Framebuffer
|
|
glGenFramebuffers(1, &Back_framebuffer);
|
|
GL_state.BindFrameBuffer(Back_framebuffer);
|
|
opengl_set_object_label(GL_FRAMEBUFFER, Back_framebuffer, "Backbuffer");
|
|
|
|
// setup main render texture
|
|
|
|
// setup high dynamic range color texture
|
|
glGenTextures(1, &Back_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Back_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, gr_screen.max_w, gr_screen.max_h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Back_texture, 0);
|
|
opengl_set_object_label(GL_TEXTURE, Back_texture, "Backbuffer texture");
|
|
|
|
glGenTextures(1, &Back_depth_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Back_depth_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D,
|
|
0,
|
|
GL_DEPTH24_STENCIL8,
|
|
gr_screen.max_w,
|
|
gr_screen.max_h,
|
|
0,
|
|
GL_DEPTH_STENCIL,
|
|
GL_UNSIGNED_INT_24_8,
|
|
nullptr);
|
|
opengl_set_object_label(GL_TEXTURE, Back_depth_texture, "Backbuffer depth texture");
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, Back_depth_texture, 0);
|
|
gr_zbuffer_set(GR_ZBUFF_FULL);
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
|
|
// Intermediate target for the gamma-correction pass. The gamma pass samples Back_texture and writes
|
|
// here (an offscreen FBO->FBO draw, same as every other post-process pass); the result is then
|
|
// presented to the window via glBlitFramebuffer. Some drivers show flicker when a shader draw that
|
|
// samples a just-rendered texture targets the window-system default framebuffer directly, so the
|
|
// final presentation step always goes through a blit instead.
|
|
glGenFramebuffers(1, &GammaBlit_framebuffer);
|
|
GL_state.BindFrameBuffer(GammaBlit_framebuffer);
|
|
opengl_set_object_label(GL_FRAMEBUFFER, GammaBlit_framebuffer, "Gamma blit framebuffer");
|
|
|
|
if (Scene_ldr_texture != 0 && Scene_texture_width == gr_screen.max_w && Scene_texture_height == gr_screen.max_h) {
|
|
// Scene_ldr_texture is dead scratch by flip time: its consumers (tonemap, AA, the final
|
|
// post pass) all write before reading within gr_opengl_post_process_end(), which completes
|
|
// before the flip. Reuse it as the gamma pass target instead of allocating another
|
|
// screen-sized texture. GammaBlit_texture stays 0 so shutdown won't delete it.
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Scene_ldr_texture, 0);
|
|
} else {
|
|
// Scene textures are clamped to GL_max_renderbuffer_size and may not cover the screen;
|
|
// fall back to a dedicated texture in that case.
|
|
glGenTextures(1, &GammaBlit_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(GammaBlit_texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gr_screen.max_w, gr_screen.max_h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, GammaBlit_texture, 0);
|
|
opengl_set_object_label(GL_TEXTURE, GammaBlit_texture, "Gamma blit texture");
|
|
}
|
|
|
|
GL_state.BindFrameBuffer(Back_framebuffer);
|
|
}
|
|
|
|
//Setup thruster distortion framebuffer
|
|
if (Gr_framebuffer_effects.any_set())
|
|
{
|
|
glGenFramebuffers(1, &Distortion_framebuffer);
|
|
GL_state.BindFrameBuffer(Distortion_framebuffer);
|
|
|
|
glGenTextures(2, Distortion_texture);
|
|
|
|
GL_state.Texture.SetActiveUnit(0);
|
|
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
|
GL_state.Texture.Enable(Distortion_texture[0]);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 32, 32, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
|
|
GL_state.Texture.Enable(Distortion_texture[1]);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 32, 32, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Distortion_texture[0], 0);
|
|
}
|
|
|
|
|
|
if ( opengl_check_framebuffer() ) {
|
|
GL_state.BindFrameBuffer(0);
|
|
glDeleteFramebuffers(1, &Distortion_framebuffer);
|
|
Distortion_framebuffer = 0;
|
|
|
|
glDeleteTextures(2, Distortion_texture);
|
|
Distortion_texture[0] = 0;
|
|
Distortion_texture[1] = 0;
|
|
return;
|
|
}
|
|
|
|
if ( opengl_check_for_errors("post_init_framebuffer()") ) {
|
|
Scene_color_texture = 0;
|
|
Scene_depth_texture = 0;
|
|
|
|
Gr_post_processing_enabled = false;
|
|
Gr_enable_soft_particles = false;
|
|
return;
|
|
}
|
|
|
|
GL_state.BindFrameBuffer(0);
|
|
|
|
Scene_texture_initialized = 1;
|
|
Scene_framebuffer_in_frame = false;
|
|
}
|
|
|
|
void opengl_scene_texture_shutdown()
|
|
{
|
|
if ( !Scene_texture_initialized ) {
|
|
return;
|
|
}
|
|
|
|
if ( Scene_color_texture ) {
|
|
glDeleteTextures(1, &Scene_color_texture);
|
|
Scene_color_texture = 0;
|
|
}
|
|
|
|
if ( Scene_position_texture ) {
|
|
glDeleteTextures(1, &Scene_position_texture);
|
|
Scene_position_texture = 0;
|
|
}
|
|
|
|
if ( Scene_normal_texture ) {
|
|
glDeleteTextures(1, &Scene_normal_texture);
|
|
Scene_normal_texture = 0;
|
|
}
|
|
|
|
if ( Scene_specular_texture ) {
|
|
glDeleteTextures(1, &Scene_specular_texture);
|
|
Scene_specular_texture = 0;
|
|
}
|
|
|
|
if (Scene_emissive_texture) {
|
|
glDeleteTextures(1, &Scene_emissive_texture);
|
|
Scene_emissive_texture = 0;
|
|
}
|
|
|
|
if ( Scene_depth_texture ) {
|
|
glDeleteTextures(1, &Scene_depth_texture);
|
|
Scene_depth_texture = 0;
|
|
}
|
|
|
|
if ( Scene_framebuffer ) {
|
|
glDeleteFramebuffers(1, &Scene_framebuffer);
|
|
Scene_framebuffer = 0;
|
|
}
|
|
|
|
if (Back_texture) {
|
|
glDeleteTextures(1, &Back_texture);
|
|
Back_texture = 0;
|
|
}
|
|
|
|
if (Back_depth_texture) {
|
|
glDeleteTextures(1, &Back_depth_texture);
|
|
Back_depth_texture = 0;
|
|
}
|
|
|
|
if (Back_framebuffer) {
|
|
glDeleteFramebuffers(1, &Back_framebuffer);
|
|
Back_framebuffer = 0;
|
|
}
|
|
|
|
if (GammaBlit_texture) {
|
|
glDeleteTextures(1, &GammaBlit_texture);
|
|
GammaBlit_texture = 0;
|
|
}
|
|
|
|
if (GammaBlit_framebuffer) {
|
|
glDeleteFramebuffers(1, &GammaBlit_framebuffer);
|
|
GammaBlit_framebuffer = 0;
|
|
}
|
|
|
|
glDeleteTextures(2, Distortion_texture);
|
|
Distortion_texture[0] = 0;
|
|
Distortion_texture[1] = 0;
|
|
|
|
if ( Distortion_framebuffer ) {
|
|
glDeleteFramebuffers(1, &Distortion_framebuffer);
|
|
Distortion_framebuffer = 0;
|
|
}
|
|
|
|
Scene_texture_initialized = 0;
|
|
Scene_framebuffer_in_frame = false;
|
|
}
|
|
|
|
size_t opengl_get_scene_render_target_bytes()
|
|
{
|
|
// The bytes for each pixel come from the internal formats that opengl_setup_scene_textures()
|
|
// gives to these textures: GL_RGBA16F holds 8 bytes, GL_RGBA8 and GL_DEPTH24_STENCIL8 hold 4.
|
|
// Keep the values below equal to the formats at the creation sites in that function.
|
|
constexpr size_t RGBA16F_BYTES = 8;
|
|
constexpr size_t RGBA8_BYTES = 4;
|
|
constexpr size_t DEPTH24_STENCIL8_BYTES = 4;
|
|
|
|
size_t bytes = 0;
|
|
|
|
auto add_texture = [&bytes](GLuint texture_id, size_t width, size_t height, size_t bytes_per_pixel,
|
|
size_t samples = 1) {
|
|
if (texture_id == 0) {
|
|
return;
|
|
}
|
|
bytes += width * height * bytes_per_pixel * samples;
|
|
};
|
|
|
|
const auto scene_w = static_cast<size_t>(Scene_texture_width);
|
|
const auto scene_h = static_cast<size_t>(Scene_texture_height);
|
|
|
|
add_texture(Scene_color_texture, scene_w, scene_h, RGBA16F_BYTES);
|
|
add_texture(Scene_ldr_texture, scene_w, scene_h, RGBA8_BYTES);
|
|
add_texture(Scene_position_texture, scene_w, scene_h, RGBA16F_BYTES);
|
|
add_texture(Scene_normal_texture, scene_w, scene_h, RGBA16F_BYTES);
|
|
add_texture(Scene_specular_texture, scene_w, scene_h, RGBA8_BYTES);
|
|
add_texture(Scene_emissive_texture, scene_w, scene_h, RGBA16F_BYTES);
|
|
add_texture(Scene_composite_texture, scene_w, scene_h, RGBA16F_BYTES);
|
|
add_texture(Scene_luminance_texture, scene_w, scene_h, RGBA16F_BYTES);
|
|
add_texture(Cockpit_depth_texture, scene_w, scene_h, DEPTH24_STENCIL8_BYTES);
|
|
add_texture(Scene_depth_texture, scene_w, scene_h, DEPTH24_STENCIL8_BYTES);
|
|
|
|
// The multisample textures hold one value for each sample, thus their bytes go up with the
|
|
// MSAA level. Cmdline_msaa_enabled holds the number of samples and is 0 when MSAA is off.
|
|
const auto samples = static_cast<size_t>(std::max(1, Cmdline_msaa_enabled));
|
|
|
|
add_texture(Scene_color_texture_ms, scene_w, scene_h, RGBA16F_BYTES, samples);
|
|
add_texture(Scene_position_texture_ms, scene_w, scene_h, RGBA16F_BYTES, samples);
|
|
add_texture(Scene_normal_texture_ms, scene_w, scene_h, RGBA16F_BYTES, samples);
|
|
add_texture(Scene_specular_texture_ms, scene_w, scene_h, RGBA8_BYTES, samples);
|
|
add_texture(Scene_emissive_texture_ms, scene_w, scene_h, RGBA16F_BYTES, samples);
|
|
add_texture(Scene_depth_texture_ms, scene_w, scene_h, DEPTH24_STENCIL8_BYTES, samples);
|
|
|
|
// The back buffer and gamma blit textures use the size of the screen, not the (clamped) size
|
|
// of the scene textures.
|
|
const auto screen_w = static_cast<size_t>(gr_screen.max_w);
|
|
const auto screen_h = static_cast<size_t>(gr_screen.max_h);
|
|
|
|
add_texture(Back_texture, screen_w, screen_h, RGBA16F_BYTES);
|
|
add_texture(Back_depth_texture, screen_w, screen_h, DEPTH24_STENCIL8_BYTES);
|
|
add_texture(GammaBlit_texture, screen_w, screen_h, RGBA8_BYTES);
|
|
|
|
// The two distortion textures always have the size 32x32.
|
|
add_texture(Distortion_texture[0], 32, 32, RGBA8_BYTES);
|
|
add_texture(Distortion_texture[1], 32, 32, RGBA8_BYTES);
|
|
|
|
return bytes;
|
|
}
|
|
|
|
void gr_opengl_scene_texture_begin()
|
|
{
|
|
if ( !Scene_texture_initialized ) {
|
|
return;
|
|
}
|
|
|
|
if ( Scene_framebuffer_in_frame ) {
|
|
return;
|
|
}
|
|
|
|
GR_DEBUG_SCOPE("Begin scene texture");
|
|
TRACE_SCOPE(tracing::SceneTextureBegin);
|
|
|
|
GL_state.PushFramebufferState();
|
|
GL_state.BindFrameBuffer(Scene_framebuffer);
|
|
|
|
// The cockpit depth mask is only written when the cockpit is actually rendered (see
|
|
// gr_opengl_post_process_save_zbuffer), and the views that skip it -- external, chase,
|
|
// topdown, warp chase -- would otherwise leave the lightshaft pass masking against the
|
|
// silhouette left over from the last cockpit-view frame. Clear it every frame; when a
|
|
// cockpit does render, save_zbuffer clears it again anyway.
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, Cockpit_depth_texture, 0);
|
|
GL_state.SetZbufferType(ZBUFFER_TYPE_FULL);
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, Scene_depth_texture, 0);
|
|
|
|
if (GL_rendering_to_texture)
|
|
{
|
|
Scene_texture_u_scale = i2fl(gr_screen.max_w) / i2fl(Scene_texture_width);
|
|
Scene_texture_v_scale = i2fl(gr_screen.max_h) / i2fl(Scene_texture_height);
|
|
|
|
CLAMP(Scene_texture_u_scale, 0.0f, 1.0f);
|
|
CLAMP(Scene_texture_v_scale, 0.0f, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
Scene_texture_u_scale = 1.0f;
|
|
Scene_texture_v_scale = 1.0f;
|
|
}
|
|
|
|
if (!light_deferred_enabled()) {
|
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
} else {
|
|
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5 };
|
|
glDrawBuffers(6, buffers);
|
|
|
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
opengl_clear_deferred_buffers();
|
|
|
|
if (Cmdline_msaa_enabled > 0) {
|
|
GL_state.BindFrameBuffer(Scene_framebuffer_ms);
|
|
|
|
glDrawBuffers(6, buffers);
|
|
|
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
opengl_clear_deferred_buffers();
|
|
|
|
GL_state.BindFrameBuffer(Scene_framebuffer);
|
|
}
|
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
|
}
|
|
|
|
Scene_framebuffer_in_frame = true;
|
|
|
|
if ( Gr_post_processing_enabled && !PostProcessing_override ) {
|
|
High_dynamic_range = true;
|
|
}
|
|
}
|
|
|
|
float time_buffer = 0.0f;
|
|
void gr_opengl_scene_texture_end()
|
|
{
|
|
|
|
if ( !Scene_framebuffer_in_frame ) {
|
|
return;
|
|
}
|
|
|
|
GR_DEBUG_SCOPE("End scene texture");
|
|
TRACE_SCOPE(tracing::SceneTextureEnd);
|
|
|
|
time_buffer+=flFrametime;
|
|
if(time_buffer>0.03f)
|
|
{
|
|
gr_opengl_update_distortion();
|
|
time_buffer = 0.0f;
|
|
}
|
|
|
|
if ( Gr_post_processing_enabled && !PostProcessing_override ) {
|
|
gr_opengl_post_process_end();
|
|
} else {
|
|
GR_DEBUG_SCOPE("Draw scene texture");
|
|
TRACE_SCOPE(tracing::DrawSceneTexture);
|
|
|
|
GLboolean depth = GL_state.DepthTest(GL_FALSE);
|
|
GLboolean depth_mask = GL_state.DepthMask(GL_FALSE);
|
|
GLboolean blend = GL_state.Blend(GL_FALSE);
|
|
GLboolean cull = GL_state.CullFace(GL_FALSE);
|
|
|
|
GL_state.PopFramebufferState();
|
|
|
|
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Scene_color_texture);
|
|
|
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
opengl_shader_set_passthrough(true, High_dynamic_range);
|
|
|
|
GL_state.Array.BindArrayBuffer(0);
|
|
|
|
if (GL_rendering_to_texture)
|
|
{
|
|
opengl_draw_textured_quad(0.0f, 0.0f, 0.0f, 0.0f, (float)gr_screen.max_w, (float)gr_screen.max_h, Scene_texture_u_scale, Scene_texture_v_scale);
|
|
}
|
|
else
|
|
{
|
|
opengl_draw_textured_quad(0.0f, 0.0f, 0.0f, Scene_texture_v_scale, (float)gr_screen.max_w, (float)gr_screen.max_h, Scene_texture_u_scale, 0.0f);
|
|
}
|
|
|
|
// reset state
|
|
GL_state.DepthTest(depth);
|
|
GL_state.DepthMask(depth_mask);
|
|
GL_state.Blend(blend);
|
|
GL_state.CullFace(cull);
|
|
}
|
|
|
|
// Reset the UV scale values
|
|
|
|
Scene_texture_u_scale = 1.0f;
|
|
Scene_texture_v_scale = 1.0f;
|
|
|
|
Scene_framebuffer_in_frame = false;
|
|
High_dynamic_range = false;
|
|
}
|
|
|
|
void gr_opengl_copy_effect_texture()
|
|
{
|
|
GR_DEBUG_SCOPE("Copy effect texture");
|
|
|
|
if ( !Scene_framebuffer_in_frame ) {
|
|
return;
|
|
}
|
|
|
|
//Make sure we're reading from the up-to-date color texture
|
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT5);
|
|
glBlitFramebuffer(0, 0, gr_screen.max_w, gr_screen.max_h, 0, 0, gr_screen.max_w, gr_screen.max_h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
|
}
|
|
|
|
void gr_opengl_render_shield_impact(shield_material* material_info,
|
|
primitive_type prim_type,
|
|
vertex_layout* layout,
|
|
gr_buffer_handle buffer_handle,
|
|
int n_verts)
|
|
{
|
|
matrix4 impact_transform;
|
|
matrix4 impact_projection;
|
|
vec3d min;
|
|
vec3d max;
|
|
|
|
opengl_tnl_set_material(material_info, false);
|
|
|
|
float radius = material_info->get_impact_radius();
|
|
min.xyz.x = min.xyz.y = min.xyz.z = -radius;
|
|
max.xyz.x = max.xyz.y = max.xyz.z = radius;
|
|
|
|
vm_matrix4_set_orthographic(&impact_projection, &max, &min);
|
|
|
|
matrix impact_orient = material_info->get_impact_orient();
|
|
vec3d impact_pos = material_info->get_impact_pos();
|
|
|
|
vm_matrix4_set_inverse_transform(&impact_transform, &impact_orient, &impact_pos);
|
|
|
|
uint32_t array_index = 0;
|
|
if (material_info->get_texture_map(TM_BASE_TYPE) >= 0) {
|
|
float u_scale, v_scale;
|
|
|
|
if (!gr_opengl_tcache_set(material_info->get_texture_map(TM_BASE_TYPE), material_info->get_texture_type(),
|
|
&u_scale, &v_scale, &array_index)) {
|
|
mprintf(("WARNING: Error setting bitmap texture (%i)!\n", material_info->get_texture_map(TM_BASE_TYPE)));
|
|
}
|
|
}
|
|
|
|
opengl_set_generic_uniform_data<graphics::generic_data::shield_impact_data>(
|
|
[&](graphics::generic_data::shield_impact_data* data) {
|
|
data->hitNormal = impact_orient.vec.fvec;
|
|
data->shieldProjMatrix = impact_projection;
|
|
data->shieldModelViewMatrix = impact_transform;
|
|
data->shieldMapIndex = array_index;
|
|
data->srgb = High_dynamic_range ? 1 : 0;
|
|
data->color = material_info->get_color();
|
|
});
|
|
|
|
gr_matrix_set_uniforms();
|
|
|
|
opengl_render_primitives(prim_type, layout, n_verts, buffer_handle, 0, 0);
|
|
}
|
|
|
|
void gr_opengl_update_distortion()
|
|
{
|
|
if (Distortion_framebuffer == 0) {
|
|
// distortion is disabled
|
|
return;
|
|
}
|
|
|
|
GR_DEBUG_SCOPE("Update distortion");
|
|
TRACE_SCOPE(tracing::UpdateDistortion);
|
|
|
|
GLboolean depth = GL_state.DepthTest(GL_FALSE);
|
|
GLboolean depth_mask = GL_state.DepthMask(GL_FALSE);
|
|
GLboolean blend = GL_state.Blend(GL_FALSE);
|
|
GLboolean cull = GL_state.CullFace(GL_FALSE);
|
|
|
|
opengl_shader_set_passthrough(true, High_dynamic_range);
|
|
|
|
GL_state.PushFramebufferState();
|
|
GL_state.BindFrameBuffer(Distortion_framebuffer);
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Distortion_texture[!Distortion_switch], 0);
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
|
|
|
glViewport(0,0,32,32);
|
|
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Distortion_texture[Distortion_switch]);
|
|
glClearColor(0.5f, 0.5f, 0.0f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
vertex vertices[4];
|
|
|
|
vertices[0].texture_position.u = 0.0f;
|
|
vertices[0].texture_position.v = 0.0f;
|
|
|
|
vertices[1].texture_position.u = 0.96875f;
|
|
vertices[1].texture_position.v = 0.0f;
|
|
|
|
vertices[2].texture_position.u = 0.0f;
|
|
vertices[2].texture_position.v = 1.0f;
|
|
|
|
vertices[3].texture_position.u = 0.96875f;
|
|
vertices[3].texture_position.v = 1.0f;
|
|
|
|
vertices[0].screen.xyw.x = 0.03f*(float)gr_screen.max_w;
|
|
vertices[0].screen.xyw.y = (float)gr_screen.max_h;
|
|
|
|
vertices[1].screen.xyw.x = (float)gr_screen.max_w;
|
|
vertices[1].screen.xyw.y = (float)gr_screen.max_h;
|
|
|
|
vertices[2].screen.xyw.x = 0.03f*(float)gr_screen.max_w;
|
|
vertices[2].screen.xyw.y = 0.0f;
|
|
|
|
vertices[3].screen.xyw.x = (float)gr_screen.max_w;
|
|
vertices[3].screen.xyw.y = 0.0f;
|
|
|
|
vertex_layout vert_def;
|
|
|
|
vert_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex), offsetof(vertex, screen));
|
|
vert_def.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex), offsetof(vertex, texture_position));
|
|
|
|
opengl_render_primitives_immediate(PRIM_TYPE_TRISTRIP, &vert_def, 4, vertices, sizeof(vertex) * 4);
|
|
|
|
opengl_shader_set_passthrough(false, High_dynamic_range);
|
|
|
|
vertex distortion_verts[33];
|
|
|
|
for(int i = 0; i < 33; i++)
|
|
{
|
|
distortion_verts[i].r = (ubyte)Random::next(256);
|
|
distortion_verts[i].g = (ubyte)Random::next(256);
|
|
distortion_verts[i].b = 255;
|
|
distortion_verts[i].a = 255;
|
|
|
|
distortion_verts[i].screen.xyw.x = 1.f;
|
|
distortion_verts[i].screen.xyw.y = (float)gr_screen.max_h*0.03125f*i;
|
|
}
|
|
|
|
vert_def = vertex_layout();
|
|
|
|
vert_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex), offsetof(vertex, screen));
|
|
vert_def.add_vertex_component(vertex_format_data::COLOR4, sizeof(vertex), offsetof(vertex, r));
|
|
|
|
opengl_render_primitives_immediate(PRIM_TYPE_POINTS, &vert_def, 33, distortion_verts, 33 * sizeof(vertex));
|
|
|
|
Distortion_switch = !Distortion_switch;
|
|
|
|
// reset state
|
|
GL_state.PopFramebufferState();
|
|
|
|
glViewport(0,0,gr_screen.max_w,gr_screen.max_h);
|
|
|
|
GL_state.DepthTest(depth);
|
|
GL_state.DepthMask(depth_mask);
|
|
GL_state.Blend(blend);
|
|
GL_state.CullFace(cull);
|
|
}
|
|
|
|
void opengl_render_primitives(primitive_type prim_type,
|
|
vertex_layout* layout,
|
|
int n_verts,
|
|
gr_buffer_handle buffer_handle,
|
|
size_t vert_offset,
|
|
size_t byte_offset)
|
|
{
|
|
GR_DEBUG_SCOPE("Render primitives");
|
|
|
|
Assertion(buffer_handle.isValid(),
|
|
"A valid buffer handle is required! Use the immediate buffer if data is not in GPU buffer yet.");
|
|
|
|
opengl_bind_vertex_layout(*layout, opengl_buffer_get_id(GL_ARRAY_BUFFER, buffer_handle), 0, byte_offset);
|
|
|
|
glDrawArrays(opengl_primitive_type(prim_type), (GLint)vert_offset, n_verts);
|
|
}
|
|
|
|
void opengl_render_primitives_immediate(primitive_type prim_type, vertex_layout* layout, int n_verts, void* data, int size)
|
|
{
|
|
auto offset = gr_add_to_immediate_buffer(size, data);
|
|
|
|
opengl_render_primitives(prim_type, layout, n_verts, gr_immediate_buffer_handle, 0, offset);
|
|
}
|
|
|
|
void gr_opengl_render_primitives(material* material_info,
|
|
primitive_type prim_type,
|
|
vertex_layout* layout,
|
|
int offset,
|
|
int n_verts,
|
|
gr_buffer_handle buffer_handle,
|
|
size_t buffer_offset)
|
|
{
|
|
GL_CHECK_FOR_ERRORS("start of gr_opengl_render_primitives()");
|
|
|
|
opengl_tnl_set_material(material_info, true);
|
|
|
|
opengl_render_primitives(prim_type, layout, n_verts, buffer_handle, offset, buffer_offset);
|
|
|
|
GL_CHECK_FOR_ERRORS("end of gr_opengl_render_primitives()");
|
|
}
|
|
|
|
void gr_opengl_render_primitives_particle(particle_material* material_info,
|
|
primitive_type prim_type,
|
|
vertex_layout* layout,
|
|
int offset,
|
|
int n_verts,
|
|
gr_buffer_handle buffer_handle)
|
|
{
|
|
GL_CHECK_FOR_ERRORS("start of gr_opengl_render_primitives_particle()");
|
|
|
|
opengl_tnl_set_material_particle(material_info);
|
|
|
|
opengl_render_primitives(prim_type, layout, n_verts, buffer_handle, offset, 0);
|
|
|
|
GL_CHECK_FOR_ERRORS("end of gr_opengl_render_primitives_particle()");
|
|
}
|
|
|
|
void gr_opengl_render_primitives_distortion(distortion_material* material_info,
|
|
primitive_type prim_type,
|
|
vertex_layout* layout,
|
|
int offset,
|
|
int n_verts,
|
|
gr_buffer_handle buffer_handle)
|
|
{
|
|
GL_CHECK_FOR_ERRORS("start of gr_opengl_render_primitives_distortion()");
|
|
|
|
opengl_tnl_set_material_distortion(material_info);
|
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
|
|
|
opengl_render_primitives(prim_type, layout, n_verts, buffer_handle, offset, 0);
|
|
|
|
GLenum buffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
|
|
glDrawBuffers(2, buffers);
|
|
|
|
GL_CHECK_FOR_ERRORS("start of gr_opengl_render_primitives_distortion()");
|
|
}
|
|
|
|
void gr_opengl_render_movie(movie_material* material_info,
|
|
primitive_type prim_type,
|
|
vertex_layout* layout,
|
|
int n_verts,
|
|
gr_buffer_handle buffer,
|
|
size_t buffer_offset)
|
|
{
|
|
GR_DEBUG_SCOPE("Render movie frame");
|
|
|
|
gr_set_2d_matrix();
|
|
|
|
opengl_tnl_set_material_movie(material_info);
|
|
|
|
opengl_render_primitives(prim_type, layout, n_verts, buffer, 0, buffer_offset);
|
|
|
|
gr_end_2d_matrix();
|
|
}
|
|
|
|
void gr_opengl_render_nanovg(nanovg_material* material_info,
|
|
primitive_type prim_type,
|
|
vertex_layout* layout,
|
|
int offset,
|
|
int n_verts,
|
|
gr_buffer_handle buffer_handle)
|
|
{
|
|
GR_DEBUG_SCOPE("Render NanoVG primitives");
|
|
|
|
opengl_tnl_set_material_nanovg(material_info);
|
|
|
|
opengl_render_primitives(prim_type, layout, n_verts, buffer_handle, offset, 0);
|
|
}
|
|
|
|
void gr_opengl_render_primitives_batched(batched_bitmap_material* material_info,
|
|
primitive_type prim_type,
|
|
vertex_layout* layout,
|
|
int offset,
|
|
int n_verts,
|
|
gr_buffer_handle buffer_handle)
|
|
{
|
|
GR_DEBUG_SCOPE("Render batched primitives");
|
|
|
|
opengl_tnl_set_material_batched(material_info);
|
|
|
|
opengl_render_primitives(prim_type, layout, n_verts, buffer_handle, offset, 0);
|
|
}
|
|
void gr_opengl_render_rocket_primitives(interface_material* material_info,
|
|
primitive_type prim_type,
|
|
vertex_layout* layout,
|
|
int n_indices,
|
|
gr_buffer_handle vertex_buffer,
|
|
gr_buffer_handle index_buffer)
|
|
{
|
|
GR_DEBUG_SCOPE("Render rocket ui primitives");
|
|
|
|
gr_set_2d_matrix();
|
|
|
|
opengl_tnl_set_rocketui_material(material_info);
|
|
|
|
opengl_bind_vertex_layout(*layout,
|
|
opengl_buffer_get_id(GL_ARRAY_BUFFER, vertex_buffer),
|
|
opengl_buffer_get_id(GL_ELEMENT_ARRAY_BUFFER, index_buffer));
|
|
|
|
glDrawElements(opengl_primitive_type(prim_type), n_indices, GL_UNSIGNED_INT, nullptr);
|
|
|
|
gr_end_2d_matrix();
|
|
}
|
|
|
|
void opengl_draw_textured_quad(GLfloat x1,
|
|
GLfloat y1,
|
|
GLfloat u1,
|
|
GLfloat v1,
|
|
GLfloat x2,
|
|
GLfloat y2,
|
|
GLfloat u2,
|
|
GLfloat v2) {
|
|
GR_DEBUG_SCOPE("Draw textured quad");
|
|
|
|
GLfloat glVertices[4][4] = {
|
|
{ x1, y1, u1, v1 },
|
|
{ x1, y2, u1, v2 },
|
|
{ x2, y1, u2, v1 },
|
|
{ x2, y2, u2, v2 }
|
|
};
|
|
|
|
vertex_layout vert_def;
|
|
|
|
vert_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(GLfloat) * 4, 0);
|
|
vert_def.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(GLfloat) * 4, sizeof(GLfloat) * 2);
|
|
|
|
opengl_render_primitives_immediate(PRIM_TYPE_TRISTRIP, &vert_def, 4, glVertices, sizeof(glVertices));
|
|
}
|
|
|
|
void opengl_draw_full_screen_textured(GLfloat u1, GLfloat v1, GLfloat u2, GLfloat v2)
|
|
{
|
|
GR_DEBUG_SCOPE("Draw full screen triangle");
|
|
|
|
GLfloat glVertices[3][4] = {
|
|
{-1.f, -1.f, u1, v1},
|
|
{3.f, -1.f, u2 * 2.f, v1},
|
|
{-1.f, 3.f, u1, v2 * 2.f},
|
|
};
|
|
|
|
vertex_layout vert_def;
|
|
|
|
vert_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(GLfloat) * 4, 0);
|
|
vert_def.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(GLfloat) * 4, sizeof(GLfloat) * 2);
|
|
|
|
opengl_render_primitives_immediate(PRIM_TYPE_TRIS, &vert_def, 3, glVertices, sizeof(glVertices));
|
|
}
|
|
|
|
void gr_opengl_render_decals(decal_material* material_info,
|
|
primitive_type prim_type,
|
|
vertex_layout* layout,
|
|
int num_elements,
|
|
const indexed_vertex_source& binding,
|
|
const gr_buffer_handle& instance_buffer,
|
|
int num_instances) {
|
|
opengl_tnl_set_material_decal(material_info);
|
|
|
|
opengl_bind_vertex_layout_multiple(*layout,
|
|
SCP_vector<GLuint> { opengl_buffer_get_id(GL_ARRAY_BUFFER, binding.Vbuffer_handle), opengl_buffer_get_id(GL_ARRAY_BUFFER, instance_buffer) },
|
|
opengl_buffer_get_id(GL_ELEMENT_ARRAY_BUFFER, binding.Ibuffer_handle));
|
|
|
|
glDrawElementsInstanced(opengl_primitive_type(prim_type), num_elements, GL_UNSIGNED_INT, nullptr, num_instances);
|
|
}
|
|
|
|
void gr_opengl_start_decal_pass() {
|
|
// For now we only render into the diffuse channel of the framebuffer
|
|
#ifndef USE_OPENGL_ES
|
|
GLenum buffers[] = {
|
|
GL_COLOR_ATTACHMENT0,
|
|
GL_COLOR_ATTACHMENT2,
|
|
GL_COLOR_ATTACHMENT4,
|
|
};
|
|
glDrawBuffers(3, buffers);
|
|
#else
|
|
GLenum buffers[] = {
|
|
GL_COLOR_ATTACHMENT0,
|
|
GL_NONE,
|
|
GL_COLOR_ATTACHMENT2,
|
|
GL_NONE,
|
|
GL_COLOR_ATTACHMENT4,
|
|
};
|
|
glDrawBuffers(5, buffers);
|
|
#endif
|
|
}
|
|
void gr_opengl_stop_decal_pass() {
|
|
GLenum buffers2[] = {
|
|
GL_COLOR_ATTACHMENT0,
|
|
GL_COLOR_ATTACHMENT1,
|
|
GL_COLOR_ATTACHMENT2,
|
|
GL_COLOR_ATTACHMENT3,
|
|
GL_COLOR_ATTACHMENT4,
|
|
GL_COLOR_ATTACHMENT5,
|
|
};
|
|
glDrawBuffers(6, buffers2);
|
|
}
|
|
|
|
void gr_opengl_calculate_irrmap()
|
|
{
|
|
|
|
auto previous_target = gr_screen.rendering_to_texture;
|
|
int irr_shader = gr_opengl_maybe_create_shader(SDR_TYPE_IRRADIANCE_MAP_GEN, 0);
|
|
opengl_shader_set_current(irr_shader);
|
|
auto env_tex = bm_get_gr_info<tcache_slot_opengl>(ENVMAP);
|
|
glBindTexture(env_tex->texture_target, env_tex->texture_id);
|
|
GL_state.Texture.Enable(0, GL_TEXTURE_CUBE_MAP, env_tex->texture_id);
|
|
Current_shader->program->Uniforms.setTextureUniform("envmap", 0);
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
bm_set_render_target(gr_screen.irrmap_render_target, i);
|
|
gr_clear();
|
|
opengl_set_generic_uniform_data<graphics::generic_data::irrmap_data>(
|
|
[&](graphics::generic_data::irrmap_data* data) { data->face = i; });
|
|
opengl_draw_full_screen_textured(-1.0f, -1.0f, 1.0f, 1.0f);
|
|
}
|
|
|
|
bm_set_render_target(previous_target);
|
|
}
|