From 083c93926f7939e95f239cbbde6de069abfb07b0 Mon Sep 17 00:00:00 2001 From: Ben Kyd Date: Wed, 15 Jan 2020 16:05:04 +0000 Subject: [PATCH] Framebuffer rendering not workin but all the code is there, need to fix KHR for debug output --- resources/2d.frag | 16 ++-- resources/2d.vert | 18 ++--- src/framebuffer.cpp | 10 +++ src/framebuffer.hpp | 3 + src/main.cpp | 27 ++++++- src/renderer.cpp | 167 +++++++++++++++++++++++++++++++--------- src/renderer.hpp | 29 ++++++- src/util/filereader.cpp | 2 + 8 files changed, 218 insertions(+), 54 deletions(-) diff --git a/resources/2d.frag b/resources/2d.frag index 7cba0d6..2b857a0 100644 --- a/resources/2d.frag +++ b/resources/2d.frag @@ -1,9 +1,13 @@ -#version 450 core +#version 430 -out vec4 outColour; +out vec4 FragColour; + +in vec2 fTextCoord; -void main() { +uniform sampler2D iTexture; - outColour = vec4(.9, .9, .9, 1); - -} \ No newline at end of file +void main() +{ + FragColour = texture(iTexture, fTextCoord); + // FragColour = vec4( 1.0, .0, .0, 1.0); // texture(iTexture, fTextCoord); +} diff --git a/resources/2d.vert b/resources/2d.vert index 93e1513..391a35e 100644 --- a/resources/2d.vert +++ b/resources/2d.vert @@ -1,14 +1,12 @@ -#version 450 core +#version 430 -layout (location = 0) in vec3 position; +layout (location = 0) in vec3 iPos; +layout (location = 1) in vec2 iTextCoord; -uniform mat4 model; -uniform mat4 view; -uniform mat4 proj; - -void main() { - - - gl_Position = proj * view * model * vec4(position, 1.0); +out vec2 fTextCoord; +void main() +{ + gl_Position = vec4(iPos, 1.0); + fTextCoord = iTextCoord; } diff --git a/src/framebuffer.cpp b/src/framebuffer.cpp index 8edb90e..644d1b0 100644 --- a/src/framebuffer.cpp +++ b/src/framebuffer.cpp @@ -66,6 +66,16 @@ void FrameBuffer::DumpToFile( std::string file ) free( imageData ); } +int FrameBuffer::GetWidth() +{ + return mWidth; +} + +int FrameBuffer::GetHeight() +{ + return mHeight; +} + FrameBuffer::~FrameBuffer() { free( Data ); diff --git a/src/framebuffer.hpp b/src/framebuffer.hpp index 0cd5980..a315542 100644 --- a/src/framebuffer.hpp +++ b/src/framebuffer.hpp @@ -16,6 +16,9 @@ public: void DumpToFile( std::string file ); + int GetWidth(); + int GetHeight(); + uint32_t* Data; ~FrameBuffer(); diff --git a/src/main.cpp b/src/main.cpp index 10d25c5..890625b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,6 +21,21 @@ struct Game SDL_GLContext GlContext = nullptr; }; +void GLAPIENTRY +MessageCallback( GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam ) +{ + std::cout << "GL CALLBACK: type = " << type + << ", severity = " << severity + << ", message = " << message << std::endl; + +} + int main() { @@ -59,12 +74,20 @@ int main() // Time to actually load OpenGL gladLoadGLLoader( SDL_GL_GetProcAddress ); + glEnable( GL_DEBUG_OUTPUT ); + glDebugMessageCallback( MessageCallback, 0 ); + Renderer renderer; renderer.LoadShader(); FrameBuffer framebuffer{ game.Width, game.Height }; framebuffer.SetPixel( 1, 1, { 1.0, 0.0, 0.0 } ); - framebuffer.DumpToFile( "image.png" ); + framebuffer.SetPixel( 2, 1, { 1.0, 0.0, 0.0 } ); + framebuffer.SetPixel( 3, 1, { 1.0, 0.0, 0.0 } ); + framebuffer.SetPixel( 4, 1, { 1.0, 0.0, 0.0 } ); + framebuffer.SetPixel( 5, 1, { 1.0, 0.0, 0.0 } ); + + renderer.RegisterBuffer( &framebuffer, 0 ); SDL_Event e; const float clearColour[] = { 186.0f / 255.0f, 214.0f / 255.0f, 254.0f / 255.0f }; @@ -78,6 +101,8 @@ int main() glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glClearBufferfv( GL_COLOR, 0, clearColour ); + renderer.Render(); + SDL_GL_SwapWindow( game.Window ); } diff --git a/src/renderer.cpp b/src/renderer.cpp index adce74c..1dd2a2a 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -1,10 +1,21 @@ #include "renderer.hpp" +#include "framebuffer.hpp" + #include Renderer::Renderer() : mFileReader() { + + // So DrawElements works, EBO can be lost as it should remain bound + GLuint indices[] = { + 0, 1, 3, 1, 2, 3 + }; + glGenBuffers( 1, &mEBO ); + glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mEBO ); + glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW ); + glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mEBO ); } @@ -18,12 +29,13 @@ bool checkShader( GLuint uid ) { char buf[512]; glGetShaderInfoLog( uid, 512, NULL, buf ); std::cout << "ERROR: " << buf << std::endl; - delete buf; + // buf gets leaked here but it was crashing + // the program so i removed the delete return false; } return true; -} +} void Renderer::LoadShader() @@ -31,60 +43,143 @@ void Renderer::LoadShader() std::string path = std::string( RESOURCES ) + "/2d"; - GLuint vert, frag; - - auto Load = [&]( std::string path, GLenum type ) - { - GLuint activeShader = 0; - - if ( type == GL_VERTEX_SHADER ) - vert = activeShader = glCreateShader( type ); - - if ( type == GL_FRAGMENT_SHADER ) - frag = activeShader = glCreateShader( type ); - - std::string loadedShaderSource = mFileReader.LoadTextFromFile( path ); - const char* shaderSource = loadedShaderSource.c_str(); - int shaderSourceLength = loadedShaderSource.length(); - - glShaderSource( activeShader, 1, &shaderSource, &shaderSourceLength ); - }; - std::string vertexLocation = path + ".vert"; - Load( vertexLocation, GL_VERTEX_SHADER ); + mLoad( vertexLocation, GL_VERTEX_SHADER ); std::cout << "Vertex shader at '" << vertexLocation << "' loaded..." << std::endl; - std::string fragmentLocation = path + ".frag"; - Load( fragmentLocation, GL_FRAGMENT_SHADER ); + mLoad( fragmentLocation, GL_FRAGMENT_SHADER ); std::cout << "Fragment shader at '" << fragmentLocation << "' loaded..." << std::endl; - - if ( vert == 0 || frag == 0 ) { + if ( mVert == 0 || mFrag == 0 ) { std::cout << "Failed to link programs: Both programs not present" << std::endl; return; } - glCompileShader( vert ); - if ( checkShader( vert ) ) { - std::cout << "Vertex shader '" << vert << "' compiled..." << std::endl; + glCompileShader( mVert ); + if ( checkShader( mVert ) ) { + std::cout << "Vertex shader '" << mVert << "' compiled..." << std::endl; } - glCompileShader( frag ); - if ( checkShader( frag ) ) { - std::cout << "Fragment shader '" << frag << "' compiled..." << std::endl; + glCompileShader( mFrag ); + if ( checkShader( mFrag ) ) { + std::cout << "Fragment shader '" << mFrag << "' compiled..." << std::endl; } mShaderProgram = glCreateProgram(); - glAttachShader( mShaderProgram, vert ); - glAttachShader( mShaderProgram, frag ); + glAttachShader( mShaderProgram, mVert ); + glAttachShader( mShaderProgram, mFrag ); glLinkProgram( mShaderProgram ); - glDeleteShader( vert ); - glDeleteShader( frag ); + glDeleteShader( mVert ); + glDeleteShader( mFrag ); glUseProgram( mShaderProgram ); } + +void Renderer::mLoad( std::string path, GLenum type ) +{ + GLuint activeShader = 0; + + if ( type == GL_VERTEX_SHADER ) + mVert = activeShader = glCreateShader( type ); + + if ( type == GL_FRAGMENT_SHADER ) + mFrag = activeShader = glCreateShader( type ); + + std::string loadedShaderSource = mFileReader.LoadTextFromFile( path ); + const char* shaderSource = loadedShaderSource.c_str(); + GLint shaderSourceLength = loadedShaderSource.length(); + + glShaderSource( activeShader, 1, &shaderSource, &shaderSourceLength ); +} + +int8_t Renderer::RegisterBuffer( FrameBuffer* buffer, int layer ) +{ + if ( buffer == nullptr ) + return -1; + + // Load buffer as a texture into OpenGL + GLuint texture; + glGenTextures( 1, &texture ); + + 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_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, buffer->GetWidth(), buffer->GetHeight(), 0, GL_RGB, GL_RGBA32UI, buffer->Data ); + + + FrameBufferRenderable fb = + { + buffer, + texture, + layer, + { + // positions // texture coords + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top right + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom right + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom left + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left + } + }; + + glGenVertexArrays( 1, &fb.VAO ); + glBindVertexArray( fb.VAO ); + + glGenBuffers( 1, &fb.VBO ); + glBindBuffer( GL_ARRAY_BUFFER, fb.VBO ); + + glBufferData( GL_ARRAY_BUFFER, 20 * sizeof( float ), &fb.QuadVerts, GL_STATIC_DRAW ); + + glEnableVertexAttribArray( 0 ); + glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof( float ), (void*)( 0 * sizeof( float ) ) ); + + glEnableVertexAttribArray( 1 ); + glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof( float ), (void*)( 3 * sizeof( float ) ) ); + + glBindVertexArray( 0 ); + + mRenderQueue.push_back( fb ); + + return mRenderQueue.size(); +} + +FrameBuffer* Renderer::GetBuffer( int8_t id ) +{ + return mRenderQueue[id].Buffer; +} + +void Renderer::UpdateBuffer( int8_t id ) +{ + if ( id > mRenderQueue.size() ) + return; + + FrameBuffer* buffer = mRenderQueue[id].Buffer; + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, buffer->GetWidth(), buffer->GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, buffer->Data ); +} + +void Renderer::Render() +{ + glUseProgram( mShaderProgram ); + glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mEBO ); + + for ( size_t i = 0; i < mRenderQueue.size(); i++ ) + { + FrameBufferRenderable* fb = &mRenderQueue[i]; + glBindTexture( GL_TEXTURE_2D, fb->TextureID ); + glBindVertexArray( fb->VAO ); + glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 ); + } +} + +Renderer::~Renderer() +{ + glDeleteProgram( mShaderProgram ); + glDeleteShader( mVert ); + glDeleteShader( mFrag ); +} diff --git a/src/renderer.hpp b/src/renderer.hpp index 9064054..4736e9b 100644 --- a/src/renderer.hpp +++ b/src/renderer.hpp @@ -7,11 +7,17 @@ class FrameBuffer; +// 3 * 4 each corner vert +// 2 * 4 each corner text +#define FRAMEBUFFER_VERTS 20 + struct FrameBufferRenderable { FrameBuffer* Buffer; GLuint TextureID; int Layer; + float QuadVerts[20]; + GLuint VAO; GLuint VBO; }; class Renderer @@ -21,13 +27,34 @@ public: void LoadShader(); - void RegisterBuffer( FrameBuffer* buffer, int layer ); + // Callee retains ownership of framebuffer + // Returns buffer ID + int8_t RegisterBuffer( FrameBuffer* buffer, int layer ); + FrameBuffer* GetBuffer( int8_t ID ); + + // Re-uploads buffer to GPU + void UpdateBuffer( int8_t ID ); + + void Render(); + + ~Renderer(); private: + // On insertion is sorted by layer + // TODO: Render by layers + // reverse referenced lists might be useful + // to retain ID but update render queues position + std::vector mRenderQueue; + FileReader mFileReader; + // GL Shaders + void mLoad( std::string path, GLenum type ); + // Used once, are invalid after LoadShader call + GLuint mVert, mFrag; GLuint mShaderProgram; + GLuint mEBO; }; diff --git a/src/util/filereader.cpp b/src/util/filereader.cpp index f9fc0d4..cdce02c 100644 --- a/src/util/filereader.cpp +++ b/src/util/filereader.cpp @@ -1,5 +1,6 @@ #include "filereader.hpp" +#include #include FileReader::FileReader() @@ -12,5 +13,6 @@ std::string FileReader::LoadTextFromFile( std::string path ) std::ifstream t( path ); std::string text( ( std::istreambuf_iterator( t ) ), std::istreambuf_iterator() ); + text += "\0"; return text; }