multisampling

This commit is contained in:
milek7
2018-07-13 00:32:25 +02:00
parent c94820e8b7
commit 0acf2da5c1
10 changed files with 96 additions and 52 deletions

View File

@@ -322,12 +322,9 @@ int main(int argc, char *argv[])
glfwWindowHint(GLFW_GREEN_BITS, vmode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS, vmode->blueBits);
glfwWindowHint(GLFW_REFRESH_RATE, vmode->refreshRate);
glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE);
glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE);
glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE);
if( Global.iMultisampling > 0 ) {
glfwWindowHint( GLFW_SAMPLES, 1 << Global.iMultisampling );
}
if (Global.bFullScreen)
{

View File

@@ -577,7 +577,7 @@ opengl_texture::bind() {
&& ( false == create() ) ) {
return false;
}
::glBindTexture( GL_TEXTURE_2D, id );
::glBindTexture( target, id );
return true;
}
@@ -595,7 +595,7 @@ opengl_texture::create() {
if( id == -1 ) {
::glGenTextures( 1, &id );
::glBindTexture( GL_TEXTURE_2D, id );
::glBindTexture( target, id );
// analyze specified texture traits
bool wraps{ true };
@@ -616,22 +616,25 @@ opengl_texture::create() {
dataheight = data_height;
if (is_rendertarget)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
if (data_components == GL_DEPTH_COMPONENT)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, borderColor);
}
glTexImage2D(GL_TEXTURE_2D, 0, data_format, data_width, data_height, 0, data_components, data_type, nullptr);
if (target == GL_TEXTURE_2D)
glTexImage2D(target, 0, data_format, data_width, data_height, 0, data_components, data_type, nullptr);
else if (target == GL_TEXTURE_2D_MULTISAMPLE)
glTexImage2DMultisample(target, samples, data_format, data_width, data_height, GL_FALSE);
}
else
{
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (wraps == true ? GL_REPEAT : GL_CLAMP_TO_EDGE));
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (wrapt == true ? GL_REPEAT : GL_CLAMP_TO_EDGE));
::glTexParameteri(target, GL_TEXTURE_WRAP_S, (wraps == true ? GL_REPEAT : GL_CLAMP_TO_EDGE));
::glTexParameteri(target, GL_TEXTURE_WRAP_T, (wrapt == true ? GL_REPEAT : GL_CLAMP_TO_EDGE));
set_filtering();
for( int maplevel = 0; maplevel < data_mapcount; ++maplevel ) {
@@ -648,7 +651,7 @@ opengl_texture::create() {
datasize = ( ( std::max( datawidth, 4 ) + 3 ) / 4 ) * ( ( std::max( dataheight, 4 ) + 3 ) / 4 ) * datablocksize;
::glCompressedTexImage2D(
GL_TEXTURE_2D, maplevel, data_format,
target, maplevel, data_format,
datawidth, dataheight, 0,
datasize, (GLubyte *)&data[ dataoffset ] );
@@ -659,7 +662,7 @@ opengl_texture::create() {
else {
// uncompressed texture data. have the gfx card do the compression as it sees fit
::glTexImage2D(
GL_TEXTURE_2D, 0,
target, 0,
Global.compress_tex ? GL_COMPRESSED_SRGB_ALPHA : GL_SRGB_ALPHA,
data_width, data_height, 0,
data_format, data_type, (GLubyte *)&data[ 0 ] );
@@ -668,7 +671,7 @@ opengl_texture::create() {
if( data_mapcount == 1 ) {
// fill missing mipmaps if needed
glGenerateMipmap(GL_TEXTURE_2D);
glGenerateMipmap(target);
}
if( ( true == Global.ResourceMove )
@@ -694,18 +697,18 @@ opengl_texture::release() {
// if resource move is enabled we don't keep a cpu side copy after upload
// so need to re-acquire the data before release
// TBD, TODO: instead of vram-ram transfer fetch the data 'normally' from the disk using worker thread
::glBindTexture( GL_TEXTURE_2D, id );
::glBindTexture(target, id );
GLint datasize {};
GLint iscompressed {};
::glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &iscompressed );
::glGetTexLevelParameteriv(target, 0, GL_TEXTURE_COMPRESSED, &iscompressed );
if( iscompressed == GL_TRUE ) {
// texture is compressed on the gpu side
// query texture details needed to perform the backup...
::glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &data_format );
::glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &datasize );
::glGetTexLevelParameteriv(target, 0, GL_TEXTURE_INTERNAL_FORMAT, &data_format );
::glGetTexLevelParameteriv(target, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &datasize );
data.resize( datasize );
// ...fetch the data...
::glGetCompressedTexImage( GL_TEXTURE_2D, 0, &data[ 0 ] );
::glGetCompressedTexImage(target, 0, &data[ 0 ] );
}
else {
// for whatever reason texture didn't get compressed during upload
@@ -714,7 +717,7 @@ opengl_texture::release() {
data_type = GL_UNSIGNED_BYTE;
data.resize( data_width * data_height * 4 );
// ...fetch the data...
::glGetTexImage( GL_TEXTURE_2D, 0, data_format, GL_UNSIGNED_BYTE, &data[ 0 ] );
::glGetTexImage(target, 0, data_format, GL_UNSIGNED_BYTE, &data[ 0 ] );
}
// ...and update texture object state
data_mapcount = 1; // we keep copy of only top mipmap level
@@ -728,7 +731,7 @@ opengl_texture::release() {
return;
}
void opengl_texture::alloc_rendertarget(GLint format, GLint components, GLint type, int width, int height)
void opengl_texture::alloc_rendertarget(GLint format, GLint components, GLint type, int width, int height, int s)
{
data_width = width;
data_height = height;
@@ -737,6 +740,9 @@ void opengl_texture::alloc_rendertarget(GLint format, GLint components, GLint ty
data_type = type;
data_mapcount = 1;
is_rendertarget = true;
samples = s;
if (samples > 1)
target = GL_TEXTURE_2D_MULTISAMPLE;
create();
}
@@ -744,12 +750,12 @@ void
opengl_texture::set_filtering() const {
// default texture mode
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
::glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
::glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
if( GLEW_EXT_texture_filter_anisotropic ) {
// anisotropic filtering
::glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, Global.AnisotropicFiltering );
::glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, Global.AnisotropicFiltering );
}
bool sharpen{ false };
@@ -891,7 +897,7 @@ texture_manager::bind( std::size_t const Unit, texture_handle const Texture ) {
if( Texture != null_handle ) {
#ifndef EU07_DEFERRED_TEXTURE_UPLOAD
// NOTE: we could bind dedicated 'error' texture here if the id isn't valid
::glBindTexture( GL_TEXTURE_2D, texture(Texture).id );
::glBindTexture( texture(Texture).target, texture(Texture).id );
m_units[ Unit ] = Texture;
#else
if( true == texture( Texture ).bind() ) {
@@ -899,7 +905,7 @@ texture_manager::bind( std::size_t const Unit, texture_handle const Texture ) {
}
else {
// TODO: bind a special 'error' texture on failure
::glBindTexture( GL_TEXTURE_2D, 0 );
::glBindTexture( texture(Texture).target, 0 );
m_units[ Unit ] = 0;
}
#endif

View File

@@ -41,7 +41,7 @@ struct opengl_texture {
height() const {
return data_height; }
void alloc_rendertarget(GLint format, GLint components, GLint type, int width, int height);
void alloc_rendertarget(GLint format, GLint components, GLint type, int width, int height, int samples = 1);
// members
GLuint id{ (GLuint)-1 }; // associated GL resource
@@ -51,6 +51,8 @@ struct opengl_texture {
std::string name; // name of the texture source file
std::size_t size{ 0 }; // size of the texture data, in kb
GLenum target = GL_TEXTURE_2D;
private:
// methods
void load_BMP();
@@ -64,6 +66,8 @@ private:
// members
bool is_rendertarget; // is used as postfx rendertarget, without loaded data
int samples;
std::vector<char> data; // texture data (stored GL-style, bottom-left origin)
resource_state data_state{ resource_state::none }; // current state of texture data
int data_width{ 0 },

View File

@@ -19,7 +19,7 @@ void gl::framebuffer::bind(GLuint id)
void gl::framebuffer::attach(const opengl_texture &tex, GLenum location)
{
bind();
glFramebufferTexture2D(GL_FRAMEBUFFER, location, GL_TEXTURE_2D, tex.id, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, location, tex.target, tex.id, 0);
}
void gl::framebuffer::attach(const renderbuffer &rb, GLenum location)
@@ -35,8 +35,21 @@ bool gl::framebuffer::is_complete()
return status == GL_FRAMEBUFFER_COMPLETE;
}
void gl::framebuffer::clear()
void gl::framebuffer::clear(GLbitfield mask)
{
bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClear(mask);
}
void gl::framebuffer::blit_to(framebuffer &other, int w, int h, GLbitfield mask)
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, *this);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, other);
glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, mask, GL_NEAREST);
unbind();
}
void gl::framebuffer::blit_from(framebuffer &other, int w, int h, GLbitfield mask)
{
other.blit_to(*this, w, h, mask);
}

View File

@@ -15,9 +15,11 @@ namespace gl
void attach(const opengl_texture &tex, GLenum location);
void attach(const renderbuffer &rb, GLenum location);
void clear();
void clear(GLbitfield mask);
bool is_complete();
void blit_to(framebuffer &other, int w, int h, GLbitfield mask);
void blit_from(framebuffer &other, int w, int h, GLbitfield mask);
using bindable::bind;
static void bind(GLuint id);

View File

@@ -25,7 +25,7 @@ void gl::postfx::apply(opengl_texture &src, framebuffer *dst)
{
if (dst)
{
dst->clear();
dst->clear(GL_COLOR_BUFFER_BIT);
dst->bind();
}
else
@@ -36,5 +36,6 @@ void gl::postfx::apply(opengl_texture &src, framebuffer *dst)
glActiveTexture(GL_TEXTURE0);
src.bind();
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

View File

@@ -17,8 +17,11 @@ void gl::renderbuffer::bind(GLuint id)
glBindRenderbuffer(GL_RENDERBUFFER, id);
}
void gl::renderbuffer::alloc(GLuint format, int width, int height)
void gl::renderbuffer::alloc(GLuint format, int width, int height, int samples)
{
bind();
glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
if (samples == 1)
glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
else
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
}

View File

@@ -11,7 +11,7 @@ namespace gl
renderbuffer();
~renderbuffer();
void alloc(GLuint format, int width, int height);
void alloc(GLuint format, int width, int height, int samples = 1);
static void bind(GLuint id);
using bindable::bind;

View File

@@ -185,15 +185,25 @@ opengl_renderer::Init( GLFWwindow *Window ) {
m_invalid_material = Fetch_Material("invalid");
m_main_fb = std::make_unique<gl::framebuffer>();
m_main_tex = std::make_unique<opengl_texture>();
m_main_rb = std::make_unique<gl::renderbuffer>();
int samples = 1 << Global.iMultisampling;
m_msaa_rbc = std::make_unique<gl::renderbuffer>();
m_msaa_rbc->alloc(GL_RGB16F, 1280, 720, samples);
m_main_rb->alloc(GL_DEPTH_COMPONENT24, 1280, 720);
m_msaa_rbd = std::make_unique<gl::renderbuffer>();
m_msaa_rbd->alloc(GL_DEPTH_COMPONENT24, 1280, 720, samples);
m_msaa_fb = std::make_unique<gl::framebuffer>();
m_msaa_fb->attach(*m_msaa_rbc, GL_COLOR_ATTACHMENT0);
m_msaa_fb->attach(*m_msaa_rbd, GL_DEPTH_ATTACHMENT);
if (!m_msaa_fb->is_complete())
return false;
m_main_tex = std::make_unique<opengl_texture>();
m_main_tex->alloc_rendertarget(GL_RGB16F, GL_RGB, GL_FLOAT, 1280, 720);
m_main_fb = std::make_unique<gl::framebuffer>();
m_main_fb->attach(*m_main_tex, GL_COLOR_ATTACHMENT0);
m_main_fb->attach(*m_main_rb, GL_DEPTH_ATTACHMENT);
if (!m_main_fb->is_complete())
return false;
@@ -312,7 +322,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
glDebug("render shadowmap end");
}
m_main_fb->bind();
m_msaa_fb->bind();
/*
if( ( true == m_environmentcubetexturesupport )
@@ -325,6 +335,8 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
*/
glViewport( 0, 0, 1280, 720 );
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
if( World.InitPerformed() ) {
auto const skydomecolour = World.Environment.m_skydome.GetAverageColor();
@@ -333,7 +345,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
else {
::glClearColor( 51.0f / 255.f, 102.0f / 255.f, 85.0f / 255.f, 1.f ); // initial background Color
}
::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
m_msaa_fb->clear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
if( World.InitPerformed() ) {
// setup
@@ -404,6 +416,9 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
}
m_main_fb->clear(GL_COLOR_BUFFER_BIT);
m_msaa_fb->blit_to(*m_main_fb.get(), 1280, 720, GL_COLOR_BUFFER_BIT);
glEnable(GL_FRAMEBUFFER_SRGB);
glViewport(0, 0, Global.iWindowWidth, Global.iWindowHeight);
m_pfx->apply(*m_main_tex, nullptr);
@@ -427,16 +442,16 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
//glEnable(GL_POLYGON_OFFSET_FILL);
//glPolygonOffset(1.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glViewport(0, 0, m_shadowbuffersize, m_shadowbuffersize);
m_shadow_fb->bind();
m_shadow_fb->clear();
m_shadow_fb->clear(GL_DEPTH_BUFFER_BIT);
setup_matrices();
setup_drawing(false);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
scene_ubs.time = Timer::GetTime();
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
scene_ubo->update(scene_ubs);
@@ -468,7 +483,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
glViewport(0, 0, EU07_PICKBUFFERSIZE, EU07_PICKBUFFERSIZE);
m_pick_fb->bind();
m_pick_fb->clear();
m_pick_fb->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);

View File

@@ -390,9 +390,12 @@ private:
std::unique_ptr<gl::program> m_line_shader;
std::unique_ptr<gl::program> m_freespot_shader;
std::unique_ptr<gl::framebuffer> m_msaa_fb;
std::unique_ptr<gl::renderbuffer> m_msaa_rbc;
std::unique_ptr<gl::renderbuffer> m_msaa_rbd;
std::unique_ptr<gl::framebuffer> m_main_fb;
std::unique_ptr<opengl_texture> m_main_tex;
std::unique_ptr<gl::renderbuffer> m_main_rb;
std::unique_ptr<gl::postfx> m_pfx;
std::unique_ptr<gl::framebuffer> m_shadow_fb;