From 5509f369a51f22d044315d79ff2128e084702933 Mon Sep 17 00:00:00 2001 From: james mintram Date: Tue, 28 Oct 2014 18:02:58 +0000 Subject: [PATCH 1/9] Initial commit for the renderer improvements --- cpp/renderer/renderer.h | 93 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 cpp/renderer/renderer.h diff --git a/cpp/renderer/renderer.h b/cpp/renderer/renderer.h new file mode 100644 index 0000000000..7471c93dc3 --- /dev/null +++ b/cpp/renderer/renderer.h @@ -0,0 +1,93 @@ +#ifndef _RENDERER_H_ +#define _RENDERER_H_ + +#include + +#include + +namespace openage { +namespace graphics { + +struct vertex2 { + float x; + float y; + + static vertex2 Create (float _x, float _y) + { + vertex2 nVertex2; + nVertex2.x = _x; + nVertex2.y = _y; + + return nVertex2; + } +}; + + +struct rect { + vertex2 topLeft; + vertex2 bottomRight; + + static Create ( vertex2 _topLeft, + vertex2 _bottomRight ) + { + rect nRect; + nRect.topLeft = _topLeft; + nRect.bottomRight = _bottomRight; + + return nRect; + } +}; + +struct renderQuad { + rect pos; + rect uv; + rect maskUV; + + float zValue; + unsigned playerID; + + + static Create ( rect const & _pos, + rect const & _uv, + rect const & _maskUV, + float _zValue, + unsigned _playerID ) + { + renderQuad nQuad; + nQuad.pos = _pos; + nQuad.uv = _uv; + nQuad.maskUV = _maskUV; + nQuad.zValue = _zValue; + nQuad.playerID = _playerID; + + return nQuad; + } +}; + +struct eMaterialType { + enum Enum { + keAlphaMask, + keColorReplace, + keNormal + }; +}; + +class Renderer { +public: + void SubmitQuad (renderQuad const & quad, + + GLint diffuse, + GLint mask, + + eMaterialType::Enum material) {} + +private: + typedef std::vector renderQuadList; + + renderQuadList renderQueue; +}; + +} +} + +#endif \ No newline at end of file From f63be9ff31f5c3826398e724af4e83b8aa3f0728 Mon Sep 17 00:00:00 2001 From: james mintram Date: Tue, 28 Oct 2014 18:42:22 +0000 Subject: [PATCH 2/9] Added a renderer class with some minimal lifetime management Added the new renderer subsystem to the build system --- cpp/CMakeLists.txt | 1 + cpp/renderer/CMakeLists.txt | 3 ++ cpp/renderer/renderer.cpp | 78 +++++++++++++++++++++++++++++++++++++ cpp/renderer/renderer.h | 28 ++++++++++--- 4 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 cpp/renderer/CMakeLists.txt create mode 100644 cpp/renderer/renderer.cpp diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index c0c3000d4a..a8b717e620 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -33,6 +33,7 @@ add_subdirectory("console") add_subdirectory("coord") add_subdirectory("job") add_subdirectory("pathfinding") +add_subdirectory("renderer") add_subdirectory("shader") add_subdirectory("util") add_subdirectory("datastructure") diff --git a/cpp/renderer/CMakeLists.txt b/cpp/renderer/CMakeLists.txt new file mode 100644 index 0000000000..89aa44b6e7 --- /dev/null +++ b/cpp/renderer/CMakeLists.txt @@ -0,0 +1,3 @@ +add_sources(${PROJECT_NAME} + renderer.cpp +) diff --git a/cpp/renderer/renderer.cpp b/cpp/renderer/renderer.cpp new file mode 100644 index 0000000000..dfe6c3e84d --- /dev/null +++ b/cpp/renderer/renderer.cpp @@ -0,0 +1,78 @@ +#include "renderer.h" + +namespace openage { +namespace graphics { + +Renderer *Renderer::instance = NULL; + +bool Renderer::create () +{ + //Idempotent + if ( instance != NULL ) return true; + + Renderer *nRenderer = new Renderer(); + + if ( nRenderer->init() ) + { + instance = nRenderer; + return true; + } + + delete nRenderer; + return false; +} + +Renderer &Renderer::get() +{ + //TODO: Should assert here if instance == NULL + + return *instance; +} + + +Renderer::Renderer () +{ + //Constructor +} + +bool Renderer::init () +{ + return true; +} + +void Renderer::submit_quad (renderQuad const & quad, + GLint diffuse, + GLint mask, + eMaterialType::Enum material) +{ + //Stuff data into vertex buffer + + //Generate a renderer key from + // MaterialType(16bit) | {textureHandle(16bit) | maskHandle(16bit)} | QuadIdx (16bit) +} + +void Renderer::render () +{ + //Sort the renderlist + //Build the index buffer (dependent on sorting order of quads) + // Build a vector of *boundries* used when rendering + + + //Bind vertex buffer + //Bind index buffer + + + //Clear the depth buffer + //Enable depth test + //Enable depth write + + + //Foreach materialtype + // bind shader + + // Foreach item in boundries + // drawelements using boundry information +} + +} +} \ No newline at end of file diff --git a/cpp/renderer/renderer.h b/cpp/renderer/renderer.h index 7471c93dc3..9c32b5fd3c 100644 --- a/cpp/renderer/renderer.h +++ b/cpp/renderer/renderer.h @@ -27,7 +27,7 @@ struct rect { vertex2 topLeft; vertex2 bottomRight; - static Create ( vertex2 _topLeft, + static rect Create ( vertex2 _topLeft, vertex2 _bottomRight ) { rect nRect; @@ -47,7 +47,7 @@ struct renderQuad { unsigned playerID; - static Create ( rect const & _pos, + static renderQuad Create ( rect const & _pos, rect const & _uv, rect const & _maskUV, float _zValue, @@ -74,17 +74,33 @@ struct eMaterialType { class Renderer { public: - void SubmitQuad (renderQuad const & quad, + void submit_quad (renderQuad const & quad, GLint diffuse, GLint mask, - eMaterialType::Enum material) {} + eMaterialType::Enum material); + + void render (); + + static bool create (); + static Renderer &get(); + +private: + + Renderer (); + bool init (); + + Renderer(const Renderer ©) = delete; + Renderer &operator=(const Renderer ©) = delete; + Renderer(Renderer &&other) = delete; + Renderer &operator=(Renderer &&other) = delete; private: - typedef std::vector renderQuadList; + typedef std::vector render_quad_list; + render_quad_list render_queue; - renderQuadList renderQueue; + static Renderer *instance; }; } From 4de1444bc5b5fe4203eb09079c8a569d93ba8497 Mon Sep 17 00:00:00 2001 From: james mintram Date: Tue, 28 Oct 2014 22:01:22 +0000 Subject: [PATCH 3/9] Shader files are loaded and linked New shader added to unify the uniform names Constified methods in dir.h/dir.cpp --- assets/shaders/alphamask.common.frag.glsl | 37 ++++++++++++ cpp/game_main.cpp | 4 ++ cpp/renderer/renderer.cpp | 72 +++++++++++++++++------ cpp/renderer/renderer.h | 63 ++++++++++++-------- cpp/util/dir.cpp | 4 +- cpp/util/dir.h | 4 +- 6 files changed, 139 insertions(+), 45 deletions(-) create mode 100644 assets/shaders/alphamask.common.frag.glsl diff --git a/assets/shaders/alphamask.common.frag.glsl b/assets/shaders/alphamask.common.frag.glsl new file mode 100644 index 0000000000..c075317401 --- /dev/null +++ b/assets/shaders/alphamask.common.frag.glsl @@ -0,0 +1,37 @@ +#version 120 + +//alpha masking shader +// +//applies an alpha mask texture to a base texture, +//then draws the masked texture. + +//the base and mask texture, base is the plain terrain tile +uniform sampler2D texture; +uniform sampler2D mask_texture; + +//disable blending and show the mask instead +uniform bool show_mask; + +//get those interpolated texture position from vertexshader +varying vec2 base_tex_position; +varying vec2 mask_tex_position; + + +void main() +{ + //get the texel from the uniform texture. + vec4 base_pixel = texture2D(texture, base_tex_position); + vec4 mask_pixel = texture2D(mask_texture, mask_tex_position); + + float factor = 1.0 - mask_pixel.x; + + vec4 blended_pixel = vec4(base_pixel.r, base_pixel.g, base_pixel.b, base_pixel.a - factor); + + //force to pink + //blended_pixel = vec4(255.0/255.0, 20.0/255.0, 147.0/255.0, 1.0); + if (show_mask) { + gl_FragColor = mask_pixel; + } else { + gl_FragColor = blended_pixel; + } +} diff --git a/cpp/game_main.cpp b/cpp/game_main.cpp index 969917c342..29c8387a17 100644 --- a/cpp/game_main.cpp +++ b/cpp/game_main.cpp @@ -20,6 +20,8 @@ #include "util/strings.h" #include "util/timer.h" +#include "renderer/renderer.h" + namespace openage { /* @@ -235,6 +237,8 @@ GameMain::GameMain(Engine *engine) // shader initialisation // read shader source codes and create shader objects for wrapping them. + graphics::Renderer::create(data_dir); + char *texture_vert_code; util::read_whole_file(&texture_vert_code, data_dir->join("shaders/maptexture.vert.glsl")); auto plaintexture_vert = new shader::Shader(GL_VERTEX_SHADER, texture_vert_code); diff --git a/cpp/renderer/renderer.cpp b/cpp/renderer/renderer.cpp index dfe6c3e84d..e762d960f8 100644 --- a/cpp/renderer/renderer.cpp +++ b/cpp/renderer/renderer.cpp @@ -1,19 +1,25 @@ #include "renderer.h" +#include "../shader/program.h" +#include "../shader/shader.h" + +#include "../util/file.h" +#include "../util/dir.h" + +#include + namespace openage { namespace graphics { Renderer *Renderer::instance = NULL; -bool Renderer::create () -{ +bool Renderer::create(util::Dir const *data_dir) { //Idempotent if ( instance != NULL ) return true; Renderer *nRenderer = new Renderer(); - if ( nRenderer->init() ) - { + if ( nRenderer->init(data_dir) ) { instance = nRenderer; return true; } @@ -22,37 +28,67 @@ bool Renderer::create () return false; } -Renderer &Renderer::get() -{ +Renderer &Renderer::get() { //TODO: Should assert here if instance == NULL return *instance; } -Renderer::Renderer () -{ - //Constructor +Renderer::Renderer() { + //Constructor } -bool Renderer::init () -{ +bool Renderer::init(util::Dir const *data_dir) { + const char *shader_file_names[][2] = { + {"shaders/maptexture.vert.glsl", "shaders/maptexture.frag.glsl"}, + {"shaders/maptexture.vert.glsl", "shaders/teamcolors.frag.glsl"}, + {"shaders/alphamask.vert.glsl", "shaders/alphamask.common.frag.glsl"}, + {NULL} + }; + + char const **cshader_file = shader_file_names[0]; + + do { + char *texture_vert_code; + util::read_whole_file(&texture_vert_code, data_dir->join(cshader_file[0])); + auto vert_shader = new shader::Shader(GL_VERTEX_SHADER, texture_vert_code); + + char *texture_frag_code; + util::read_whole_file(&texture_frag_code, data_dir->join(cshader_file[1])); + auto frag_shader = new shader::Shader(GL_FRAGMENT_SHADER, texture_frag_code); + + material &cMaterial = materials[eMaterialType::keNormal]; + + cMaterial.program = new shader::Program(vert_shader, frag_shader); + cMaterial.program->link(); + + cMaterial.uniformNormalTexture = cMaterial.program->get_uniform_id("texture"); + cMaterial.uniformUV = cMaterial.program->get_uniform_id("tex_coordinates"); + + cMaterial.uniformMasktexture = cMaterial.program->get_uniform_id("mask_texture"); + cMaterial.uniformMaskUV = cMaterial.program->get_uniform_id("mask_tex_coordinates"); + + delete[] texture_vert_code; + delete[] texture_frag_code; + + cshader_file += sizeof(shader_file_names[0]) / sizeof(shader_file_names[0][0]); + } while ( cshader_file[0] != NULL ); + return true; } -void Renderer::submit_quad (renderQuad const & quad, - GLint diffuse, - GLint mask, - eMaterialType::Enum material) -{ +void Renderer::submit_quad(render_quad const & quad, + GLint diffuse, + GLint mask, + eMaterialType::Enum material_type) { //Stuff data into vertex buffer //Generate a renderer key from // MaterialType(16bit) | {textureHandle(16bit) | maskHandle(16bit)} | QuadIdx (16bit) } -void Renderer::render () -{ +void Renderer::render() { //Sort the renderlist //Build the index buffer (dependent on sorting order of quads) // Build a vector of *boundries* used when rendering diff --git a/cpp/renderer/renderer.h b/cpp/renderer/renderer.h index 9c32b5fd3c..db1674ad94 100644 --- a/cpp/renderer/renderer.h +++ b/cpp/renderer/renderer.h @@ -5,15 +5,23 @@ #include + namespace openage { + +namespace shader { + class Program; +} +namespace util { + class Dir; +} + namespace graphics { struct vertex2 { float x; float y; - static vertex2 Create (float _x, float _y) - { + static vertex2 Create (float _x, float _y) { vertex2 nVertex2; nVertex2.x = _x; nVertex2.y = _y; @@ -27,9 +35,8 @@ struct rect { vertex2 topLeft; vertex2 bottomRight; - static rect Create ( vertex2 _topLeft, - vertex2 _bottomRight ) - { + static rect Create( vertex2 _topLeft, + vertex2 _bottomRight ) { rect nRect; nRect.topLeft = _topLeft; nRect.bottomRight = _bottomRight; @@ -38,7 +45,7 @@ struct rect { } }; -struct renderQuad { +struct render_quad { rect pos; rect uv; rect maskUV; @@ -47,13 +54,12 @@ struct renderQuad { unsigned playerID; - static renderQuad Create ( rect const & _pos, - rect const & _uv, - rect const & _maskUV, - float _zValue, - unsigned _playerID ) - { - renderQuad nQuad; + static render_quad Create ( rect const & _pos, + rect const & _uv, + rect const & _maskUV, + float _zValue, + unsigned _playerID ) { + render_quad nQuad; nQuad.pos = _pos; nQuad.uv = _uv; nQuad.maskUV = _maskUV; @@ -68,28 +74,37 @@ struct eMaterialType { enum Enum { keAlphaMask, keColorReplace, - keNormal + keNormal, + + keCount }; }; +struct material { + shader::Program *program; + GLint uniformNormalTexture; + GLint uniformMasktexture; + + GLint uniformUV; + GLint uniformMaskUV; +}; + class Renderer { public: - void submit_quad (renderQuad const & quad, - - GLint diffuse, - GLint mask, - - eMaterialType::Enum material); + void submit_quad (render_quad const & quad, + GLint diffuse, + GLint mask, + eMaterialType::Enum material_type); void render (); - static bool create (); + static bool create (util::Dir const *data_dir); static Renderer &get(); private: Renderer (); - bool init (); + bool init (util::Dir const *data_dir); Renderer(const Renderer ©) = delete; Renderer &operator=(const Renderer ©) = delete; @@ -97,9 +112,11 @@ class Renderer { Renderer &operator=(Renderer &&other) = delete; private: - typedef std::vector render_quad_list; + typedef std::vector render_quad_list; render_quad_list render_queue; + material materials[eMaterialType::keCount]; + static Renderer *instance; }; diff --git a/cpp/util/dir.cpp b/cpp/util/dir.cpp index 3f1fde1625..c957c7301d 100644 --- a/cpp/util/dir.cpp +++ b/cpp/util/dir.cpp @@ -11,11 +11,11 @@ Dir::Dir(std::string basedir) { Dir::~Dir() {} -std::string Dir::join(const std::string &fname) { +std::string Dir::join(const std::string &fname) const { return this->basedir + PATHSEP + fname; } -Dir Dir::append(const std::string &suffix) { +Dir Dir::append(const std::string &suffix) const { if (suffix.length() == 0) { return Dir{this->basedir}; } else { diff --git a/cpp/util/dir.h b/cpp/util/dir.h index 4ea3533986..a10768835e 100644 --- a/cpp/util/dir.h +++ b/cpp/util/dir.h @@ -18,8 +18,8 @@ class Dir { Dir(std::string basedir); ~Dir(); - std::string join(const std::string &fname); - Dir append(const std::string &suffix); + std::string join(const std::string &fname) const; + Dir append(const std::string &suffix) const; std::string basedir; }; From 6212907a8697d3d5f80121301ad183c055d14ef0 Mon Sep 17 00:00:00 2001 From: james mintram Date: Wed, 29 Oct 2014 01:34:46 +0000 Subject: [PATCH 4/9] Graphics can now be partially rendered through the new renderer but still using the inefficient process as before --- assets/shaders/alphamask.common.vert.glsl | 25 +++++ cpp/renderer/renderer.cpp | 125 ++++++++++++++++++++-- cpp/renderer/renderer.h | 53 ++++++--- cpp/shader/program.cpp | 10 ++ cpp/shader/program.h | 2 + cpp/texture.cpp | 34 +++++- 6 files changed, 219 insertions(+), 30 deletions(-) create mode 100644 assets/shaders/alphamask.common.vert.glsl diff --git a/assets/shaders/alphamask.common.vert.glsl b/assets/shaders/alphamask.common.vert.glsl new file mode 100644 index 0000000000..6bd0e4e4a3 --- /dev/null +++ b/assets/shaders/alphamask.common.vert.glsl @@ -0,0 +1,25 @@ +//vertex shader for applying an alpha mask to a texture +#version 120 + +//modelview*projection matrix +uniform mat4 mvp_matrix; + +//the position of this vertex +attribute vec4 vertex_position; + +//send the texture coordinates to the fragmentshader +attribute vec2 tex_coordinates; +attribute vec2 mask_tex_coordinates; + +//send the texture coordinates to the fragmentshader +varying vec2 base_tex_position; +varying vec2 mask_tex_position; + +void main(void) { + //transform the position with the mvp matrix + gl_Position = gl_ModelViewProjectionMatrix * vertex_position; + + //set the fixpoints for the tex coordinates at this vertex + mask_tex_position = mask_tex_coordinates; + base_tex_position = tex_coordinates; +} diff --git a/cpp/renderer/renderer.cpp b/cpp/renderer/renderer.cpp index e762d960f8..5db896eb70 100644 --- a/cpp/renderer/renderer.cpp +++ b/cpp/renderer/renderer.cpp @@ -12,7 +12,11 @@ namespace openage { namespace graphics { Renderer *Renderer::instance = NULL; - + +//Local for now +GLuint vertbuf; + + bool Renderer::create(util::Dir const *data_dir) { //Idempotent if ( instance != NULL ) return true; @@ -43,13 +47,18 @@ bool Renderer::init(util::Dir const *data_dir) { const char *shader_file_names[][2] = { {"shaders/maptexture.vert.glsl", "shaders/maptexture.frag.glsl"}, {"shaders/maptexture.vert.glsl", "shaders/teamcolors.frag.glsl"}, - {"shaders/alphamask.vert.glsl", "shaders/alphamask.common.frag.glsl"}, + {"shaders/alphamask.common.vert.glsl", "shaders/alphamask.common.frag.glsl"}, {NULL} }; - char const **cshader_file = shader_file_names[0]; - do { + + for ( int cmaterial_idx = 0; cmaterial_idx < eMaterialType::keCount; cmaterial_idx++) + { + char const **cshader_file = shader_file_names[cmaterial_idx]; + + printf ("Loading shaders: %s %s\n", cshader_file[0], cshader_file[1]); + char *texture_vert_code; util::read_whole_file(&texture_vert_code, data_dir->join(cshader_file[0])); auto vert_shader = new shader::Shader(GL_VERTEX_SHADER, texture_vert_code); @@ -58,22 +67,33 @@ bool Renderer::init(util::Dir const *data_dir) { util::read_whole_file(&texture_frag_code, data_dir->join(cshader_file[1])); auto frag_shader = new shader::Shader(GL_FRAGMENT_SHADER, texture_frag_code); - material &cMaterial = materials[eMaterialType::keNormal]; + material &cMaterial = materials[cmaterial_idx]; cMaterial.program = new shader::Program(vert_shader, frag_shader); cMaterial.program->link(); cMaterial.uniformNormalTexture = cMaterial.program->get_uniform_id("texture"); - cMaterial.uniformUV = cMaterial.program->get_uniform_id("tex_coordinates"); - cMaterial.uniformMasktexture = cMaterial.program->get_uniform_id("mask_texture"); - cMaterial.uniformMaskUV = cMaterial.program->get_uniform_id("mask_tex_coordinates"); + + //Needs to be an attribute + cMaterial.attributeMaskUV = (cMaterial.program->has_attribute("mask_tex_coordinates")) ? + cMaterial.program->get_attribute_id("mask_tex_coordinates") + : -1; + + cMaterial.attributeUV = (cMaterial.program->has_attribute("tex_coordinates")) ? + cMaterial.program->get_attribute_id("tex_coordinates") + : -1; + + cMaterial.program->use(); + glUniform1i(cMaterial.uniformNormalTexture, 0); + glUniform1i(cMaterial.uniformMasktexture, 1); + cMaterial.program->stopusing(); delete[] texture_vert_code; delete[] texture_frag_code; - - cshader_file += sizeof(shader_file_names[0]) / sizeof(shader_file_names[0][0]); - } while ( cshader_file[0] != NULL ); + } + + glGenBuffers(1, &vertbuf); return true; } @@ -86,6 +106,89 @@ void Renderer::submit_quad(render_quad const & quad, //Generate a renderer key from // MaterialType(16bit) | {textureHandle(16bit) | maskHandle(16bit)} | QuadIdx (16bit) + + + //For now we will render to quad immeadiatly (to make the transition easier) + + //if ( material_type != eMaterialType::keNormal ) return; + if ( material_type == eMaterialType::keAlphaMask ) return; + + // + // Pre rendering per material type + // + + switch (material_type) { + case eMaterialType::keNormal: { + //Render a normal texture here + break; + } + default: { + //Do nothing here + break; + } + } + + material current_material = materials[material_type]; + + current_material.program->use(); + + glActiveTexture(GL_TEXTURE0); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, diffuse); + + //Bind vertex buffers here + glBindBuffer(GL_ARRAY_BUFFER, vertbuf); + glBufferData(GL_ARRAY_BUFFER, sizeof(render_quad), &quad.vertices, GL_STREAM_DRAW); + + +// Need to retrieve the attributes from the shaders before we can use them here + glEnableVertexAttribArray(current_material.program->pos_id); + glEnableVertexAttribArray(current_material.attributeUV); + + //set data types, offsets in the vdata array + glVertexAttribPointer(current_material.program->pos_id, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, pos)); + + glVertexAttribPointer(current_material.attributeUV, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, uv)); + + //Set the masking layer here + + //draw the vertex array + glDrawArrays(GL_QUADS, 0, 4); + + glDisableVertexAttribArray(current_material.program->pos_id); + glDisableVertexAttribArray(current_material.attributeUV); + + //unbind the current buffer + glBindBuffer(GL_ARRAY_BUFFER, 0); + + current_material.program->stopusing(); + + // + // Post rendering per material type + // + switch (material_type) { + case eMaterialType::keNormal: { + //Render a normal texture here + break; + } + default: { + //Do nothing here + break; + } + } + + glActiveTexture(GL_TEXTURE0); + glDisable(GL_TEXTURE_2D); } void Renderer::render() { diff --git a/cpp/renderer/renderer.h b/cpp/renderer/renderer.h index db1674ad94..9453fff899 100644 --- a/cpp/renderer/renderer.h +++ b/cpp/renderer/renderer.h @@ -46,25 +46,46 @@ struct rect { }; struct render_quad { - rect pos; - rect uv; - rect maskUV; - - float zValue; - unsigned playerID; - + struct quad_vertex { + vertex2 pos; + vertex2 uv; + vertex2 maskUV; + float zValue; + unsigned playerID; + }; + quad_vertex vertices[4]; + static render_quad Create ( rect const & _pos, rect const & _uv, rect const & _maskUV, float _zValue, unsigned _playerID ) { render_quad nQuad; - nQuad.pos = _pos; - nQuad.uv = _uv; - nQuad.maskUV = _maskUV; - nQuad.zValue = _zValue; - nQuad.playerID = _playerID; + + nQuad.vertices[0].pos = _pos.topLeft; + nQuad.vertices[0].uv = _uv.topLeft; + nQuad.vertices[0].maskUV = _maskUV.topLeft; + nQuad.vertices[0].zValue = _zValue; + nQuad.vertices[0].playerID = _playerID; + + nQuad.vertices[1].pos = vertex2::Create(_pos.topLeft.x, _pos.bottomRight.y); + nQuad.vertices[1].uv = vertex2::Create(_uv.topLeft.x, _uv.bottomRight.y); + nQuad.vertices[1].maskUV = vertex2::Create(_maskUV.topLeft.x, _maskUV.bottomRight.y); + nQuad.vertices[1].zValue = _zValue; + nQuad.vertices[1].playerID = _playerID; + + nQuad.vertices[2].pos = _pos.bottomRight; + nQuad.vertices[2].uv = _uv.bottomRight; + nQuad.vertices[2].maskUV = _maskUV.bottomRight; + nQuad.vertices[2].zValue = _zValue; + nQuad.vertices[2].playerID = _playerID; + + nQuad.vertices[3].pos = vertex2::Create(_pos.bottomRight.x, _pos.topLeft.y); + nQuad.vertices[3].uv = vertex2::Create(_uv.bottomRight.x, _uv.topLeft.y); + nQuad.vertices[3].maskUV = vertex2::Create(_maskUV.bottomRight.x, _maskUV.topLeft.y); + nQuad.vertices[3].zValue = _zValue; + nQuad.vertices[3].playerID = _playerID; return nQuad; } @@ -72,9 +93,9 @@ struct render_quad { struct eMaterialType { enum Enum { - keAlphaMask, - keColorReplace, keNormal, + keColorReplace, + keAlphaMask, keCount }; @@ -85,8 +106,8 @@ struct material { GLint uniformNormalTexture; GLint uniformMasktexture; - GLint uniformUV; - GLint uniformMaskUV; + GLint attributeUV; + GLint attributeMaskUV; }; class Renderer { diff --git a/cpp/shader/program.cpp b/cpp/shader/program.cpp index 9437230a9e..80743a7a1f 100644 --- a/cpp/shader/program.cpp +++ b/cpp/shader/program.cpp @@ -108,6 +108,16 @@ GLint Program::get_uniform_id(const char *name) { return glGetUniformLocation(this->id, name); } +bool Program::has_attribute(const char *name) { + if (this->is_linked) { + GLint aid = glGetAttribLocation(this->id, name); + return aid != -1; + } + else { + throw util::Error("queried attribute '%s' id before program was linked.", name); + } +} + GLint Program::get_attribute_id(const char *name) { if (this->is_linked) { GLint aid = glGetAttribLocation(this->id, name); diff --git a/cpp/shader/program.h b/cpp/shader/program.h index f38b5068ed..c93af74acb 100644 --- a/cpp/shader/program.h +++ b/cpp/shader/program.h @@ -25,6 +25,8 @@ class Program { void use(); void stopusing(); + bool has_attribute(const char *name); + GLint get_uniform_id(const char *name); GLint get_attribute_id(const char *name); diff --git a/cpp/texture.cpp b/cpp/texture.cpp index 6452211596..73f5c68217 100644 --- a/cpp/texture.cpp +++ b/cpp/texture.cpp @@ -10,6 +10,10 @@ #include "util/error.h" #include "util/file.h" +#include "renderer/renderer.h" + +using namespace openage::graphics; + namespace openage { //real definition of the shaders, @@ -150,7 +154,8 @@ void Texture::draw(coord::pixel_t x, coord::pixel_t y, bool mirrored, int subid, glColor4f(1, 1, 1, 1); //log::dbg("drawing texture at %hd, %hd", x, y); - + eMaterialType::Enum cType; //Use this to help transition to new renderer + bool use_playercolors = false; bool use_alphashader = false; struct gamedata::subtexture *mtx; @@ -172,6 +177,8 @@ void Texture::draw(coord::pixel_t x, coord::pixel_t y, bool mirrored, int subid, texcoord_id = &alphamask_shader::base_coord; masktexcoord_id = &alphamask_shader::mask_coord; use_alphashader = true; + + cType = eMaterialType::keAlphaMask; } //is this texure drawn with replaced pixels for team coloring? else if (this->use_player_color_tinting) { @@ -182,12 +189,16 @@ void Texture::draw(coord::pixel_t x, coord::pixel_t y, bool mirrored, int subid, pos_id = &teamcolor_shader::program->pos_id; texcoord_id = &teamcolor_shader::tex_coord; use_playercolors = true; + + cType = eMaterialType::keColorReplace; } //mkay, we just draw the plain texture otherwise. else { texture_shader::program->use(); pos_id = &texture_shader::program->pos_id; texcoord_id = &texture_shader::tex_coord; + + cType = eMaterialType::keNormal; } glActiveTexture(GL_TEXTURE0); @@ -246,7 +257,6 @@ void Texture::draw(coord::pixel_t x, coord::pixel_t y, bool mirrored, int subid, mtxr, mtxt }; - //store vertex buffer data, TODO: prepare this sometime earlier. glBindBuffer(GL_ARRAY_BUFFER, this->vertbuf); glBufferData(GL_ARRAY_BUFFER, sizeof(vdata), vdata, GL_STREAM_DRAW); @@ -265,8 +275,9 @@ void Texture::draw(coord::pixel_t x, coord::pixel_t y, bool mirrored, int subid, glVertexAttribPointer(*masktexcoord_id, 2, GL_FLOAT, GL_FALSE, 0, (void *)(sizeof(float) * 8 * 2)); } + //draw the vertex array - glDrawArrays(GL_QUADS, 0, 4); + //glDrawArrays(GL_QUADS, 0, 4); //unbind the current buffer glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -290,6 +301,23 @@ void Texture::draw(coord::pixel_t x, coord::pixel_t y, bool mirrored, int subid, glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); + + + Renderer::get().submit_quad(render_quad::Create( + //Position to render to + rect::Create(vertex2::Create(leftf, topf), + vertex2::Create(rightf, bottomf)), + //UV coords for texture + rect::Create(vertex2::Create(txl, txt), + vertex2::Create(txr, txb)), + //UV coords for mask texture + rect::Create(vertex2::Create(mtxl, mtxt), + vertex2::Create(mtxr, mtxb)), + 0, //z-value + 0), //playerID + this->id, //diffuse + this->id, //Mask + cType); } From 6e19516bcd63f28ddf84345bbf69ad86a843205e Mon Sep 17 00:00:00 2001 From: james mintram Date: Wed, 29 Oct 2014 22:57:14 +0000 Subject: [PATCH 5/9] Removed tons of code from the recolouring shader Updated shaders to work with attributes instead of uniforms At the halfway house - rendering is performed within the renderer file using the information that will be cached (but it still renders immediately) --- assets/shaders/maptexture.vert.glsl | 4 + assets/shaders/teamcolors.frag.glsl | 63 ++++----------- cpp/game_main.cpp | 2 +- cpp/renderer/renderer.cpp | 100 +++++++++++++++++++++-- cpp/renderer/renderer.h | 8 +- cpp/texture.cpp | 118 +++------------------------- 6 files changed, 130 insertions(+), 165 deletions(-) diff --git a/assets/shaders/maptexture.vert.glsl b/assets/shaders/maptexture.vert.glsl index b1391a8869..607a7ef788 100644 --- a/assets/shaders/maptexture.vert.glsl +++ b/assets/shaders/maptexture.vert.glsl @@ -10,8 +10,11 @@ attribute vec4 vertex_position; //the texture coordinates assigned to this vertex attribute vec2 tex_coordinates; +attribute float player_number; + //interpolated texture coordinates sent to fragment shader varying vec2 tex_position; +varying float vplayer_number; void main(void) { //transform the vertex coordinates @@ -19,4 +22,5 @@ void main(void) { //pass the fix points for texture coordinates set at this vertex tex_position = tex_coordinates; + vplayer_number = player_number; } diff --git a/assets/shaders/teamcolors.frag.glsl b/assets/shaders/teamcolors.frag.glsl index fe411ebb22..ff6641424f 100644 --- a/assets/shaders/teamcolors.frag.glsl +++ b/assets/shaders/teamcolors.frag.glsl @@ -9,9 +9,6 @@ //the unmodified texture itself uniform sampler2D texture; -//the desired player number the final resulting colors -uniform int player_number; - //the alpha value which marks colors to be replaced uniform float alpha_marker; @@ -21,59 +18,31 @@ uniform vec4 player_color[64]; //interpolated texture coordinates sent from vertex shader varying vec2 tex_position; +//the desired player number the final resulting colors +varying float vplayer_number; +varying float vz_order; + //create epsilon environment for float comparison const float epsilon = 0.001; - -//do the lookup in the player color table -//for a playernumber (red, blue, etc) -//get the subcolor (brightness variations) -vec4 get_color(int playernum, int subcolor) { - return player_color[((playernum-1) * 8) + subcolor]; -} - -//compare color c1 to a reference color -bool is_color(vec4 c1, vec4 reference) { - if (all(greaterThanEqual(c1, reference - epsilon)) && all(lessThanEqual(c1, reference + epsilon))) { - return true; - } - else { - return false; - } -} +const vec3 vepsilon = vec3(epsilon, epsilon, epsilon); void main() { //get the texel from the uniform texture. vec4 pixel = texture2D(texture, tex_position); - //check if this texel has an alpha marker, so we can replace it's rgb values. - if (pixel[3] >= alpha_marker - epsilon && pixel[3] <= alpha_marker + epsilon) { - - //set alpha to 1 for the comparison - pixel[3] = 1.0; - - //don't replace the colors if it's already player 1 (blue) - //as the media convert scripts generates blue-player sprites - if (player_number != 1) { - bool found = false; - - //try to find the base color, there are 8 of them. - for(int i = 0; i <= 7; i++) { - if (is_color(pixel, player_color[i])) { - //base color found, now replace it with the same color - //but player_number tinted. - pixel = get_color(player_number, i); - found = true; - break; - } - } - if (!found) { - //unknown base color gets pink muhahaha - pixel = vec4(255.0/255.0, 20.0/255.0, 147.0/255.0, 1.0); - } + if ( abs(pixel.a - alpha_marker) > epsilon ) + { + //Even replace player 1's colours as we then remove a branch + for(int i = 0; i <= 7; i++) { + if ( all(lessThanEqual(abs(pixel.rgb - player_color[i].rgb), vepsilon)) ) + { + pixel = player_color[int( ((vplayer_number-1) * 8) + i )]; + //pixel = vec4(1, 1, 1, 1); + break; + } } } - //else the texel had no marker so we can just draw it without player coloring gl_FragColor = pixel; -} +} \ No newline at end of file diff --git a/cpp/game_main.cpp b/cpp/game_main.cpp index 29c8387a17..ae2efd6d82 100644 --- a/cpp/game_main.cpp +++ b/cpp/game_main.cpp @@ -237,7 +237,7 @@ GameMain::GameMain(Engine *engine) // shader initialisation // read shader source codes and create shader objects for wrapping them. - graphics::Renderer::create(data_dir); + graphics::Renderer::create(data_dir, &asset_dir); char *texture_vert_code; util::read_whole_file(&texture_vert_code, data_dir->join("shaders/maptexture.vert.glsl")); diff --git a/cpp/renderer/renderer.cpp b/cpp/renderer/renderer.cpp index 5db896eb70..8fe5da3a9d 100644 --- a/cpp/renderer/renderer.cpp +++ b/cpp/renderer/renderer.cpp @@ -5,6 +5,8 @@ #include "../util/file.h" #include "../util/dir.h" +#include "../gamedata/color.gen.h" + #include @@ -17,13 +19,13 @@ Renderer *Renderer::instance = NULL; GLuint vertbuf; -bool Renderer::create(util::Dir const *data_dir) { +bool Renderer::create(util::Dir const *data_dir, util::Dir const *asset_dir) { //Idempotent if ( instance != NULL ) return true; Renderer *nRenderer = new Renderer(); - if ( nRenderer->init(data_dir) ) { + if ( nRenderer->init(data_dir, asset_dir) ) { instance = nRenderer; return true; } @@ -43,7 +45,7 @@ Renderer::Renderer() { //Constructor } -bool Renderer::init(util::Dir const *data_dir) { +bool Renderer::init(util::Dir const *data_dir, util::Dir const *asset_dir) { const char *shader_file_names[][2] = { {"shaders/maptexture.vert.glsl", "shaders/maptexture.frag.glsl"}, {"shaders/maptexture.vert.glsl", "shaders/teamcolors.frag.glsl"}, @@ -74,6 +76,7 @@ bool Renderer::init(util::Dir const *data_dir) { cMaterial.uniformNormalTexture = cMaterial.program->get_uniform_id("texture"); cMaterial.uniformMasktexture = cMaterial.program->get_uniform_id("mask_texture"); + cMaterial.uniformPlayerColors = cMaterial.program->get_uniform_id("player_color"); //Needs to be an attribute cMaterial.attributeMaskUV = (cMaterial.program->has_attribute("mask_tex_coordinates")) ? @@ -83,6 +86,16 @@ bool Renderer::init(util::Dir const *data_dir) { cMaterial.attributeUV = (cMaterial.program->has_attribute("tex_coordinates")) ? cMaterial.program->get_attribute_id("tex_coordinates") : -1; + + cMaterial.attributePlayerCol = (cMaterial.program->has_attribute("player_number")) ? + cMaterial.program->get_attribute_id("player_number") + : -1; + + cMaterial.attributeZOrder = (cMaterial.program->has_attribute("z_order")) ? + cMaterial.program->get_attribute_id("z_order") + : -1; + + //Fixup material specific cMaterial.program->use(); glUniform1i(cMaterial.uniformNormalTexture, 0); @@ -93,6 +106,27 @@ bool Renderer::init(util::Dir const *data_dir) { delete[] texture_frag_code; } + { + //fixup material specific normals + auto player_color_lines = util::read_csv_file(asset_dir->join("player_palette_50500.docx")); + + GLfloat *playercolors = new GLfloat[player_color_lines.size() * 4]; + for (size_t i = 0; i < player_color_lines.size(); i++) { + auto line = &player_color_lines[i]; + playercolors[i*4] = line->r / 255.0; + playercolors[i*4 + 1] = line->g / 255.0; + playercolors[i*4 + 2] = line->b / 255.0; + playercolors[i*4 + 3] = line->a / 255.0; + } + + + // + // TODO: Update these to a 1D texture + // + materials[eMaterialType::keColorReplace].program->use(); + glUniform4fv(materials[eMaterialType::keColorReplace].uniformPlayerColors, 64, playercolors); + materials[eMaterialType::keColorReplace].program->stopusing(); + } glGenBuffers(1, &vertbuf); return true; @@ -110,9 +144,6 @@ void Renderer::submit_quad(render_quad const & quad, //For now we will render to quad immeadiatly (to make the transition easier) - //if ( material_type != eMaterialType::keNormal ) return; - if ( material_type == eMaterialType::keAlphaMask ) return; - // // Pre rendering per material type // @@ -122,6 +153,12 @@ void Renderer::submit_quad(render_quad const & quad, //Render a normal texture here break; } + case eMaterialType::keAlphaMask: { + //bind the alpha mask texture to slot 1 + glActiveTexture(GL_TEXTURE1); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, mask); + } default: { //Do nothing here break; @@ -144,6 +181,7 @@ void Renderer::submit_quad(render_quad const & quad, // Need to retrieve the attributes from the shaders before we can use them here glEnableVertexAttribArray(current_material.program->pos_id); glEnableVertexAttribArray(current_material.attributeUV); + //set data types, offsets in the vdata array glVertexAttribPointer(current_material.program->pos_id, @@ -160,6 +198,38 @@ void Renderer::submit_quad(render_quad const & quad, sizeof(render_quad::quad_vertex), (void*)offsetof(render_quad::quad_vertex, uv)); + if ( material_type == eMaterialType::keAlphaMask ) { + glEnableVertexAttribArray(current_material.attributeMaskUV); + glVertexAttribPointer(current_material.attributeMaskUV, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, maskUV)); + } + + //These checks are temporary + if ( current_material.attributePlayerCol != -1 ) + { + glEnableVertexAttribArray(current_material.attributePlayerCol); + glVertexAttribPointer(current_material.attributePlayerCol, + 1, + GL_UNSIGNED_INT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, playerID)); + } + if ( current_material.attributeZOrder != -1 ) + { + glEnableVertexAttribArray(current_material.attributeZOrder); + glVertexAttribPointer(current_material.attributeZOrder, + 1, + GL_FLOAT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, zValue)); + } + //Set the masking layer here //draw the vertex array @@ -167,7 +237,17 @@ void Renderer::submit_quad(render_quad const & quad, glDisableVertexAttribArray(current_material.program->pos_id); glDisableVertexAttribArray(current_material.attributeUV); - + + //These checks are temporary + if ( current_material.attributePlayerCol != -1 ) + { + glDisableVertexAttribArray(current_material.attributePlayerCol); + } + if ( current_material.attributeZOrder != -1 ) + { + glDisableVertexAttribArray(current_material.attributeZOrder); + } + //unbind the current buffer glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -181,6 +261,12 @@ void Renderer::submit_quad(render_quad const & quad, //Render a normal texture here break; } + case eMaterialType::keAlphaMask: { + glDisableVertexAttribArray(current_material.attributeMaskUV); + + glActiveTexture(GL_TEXTURE1); + glDisable(GL_TEXTURE_2D); + } default: { //Do nothing here break; diff --git a/cpp/renderer/renderer.h b/cpp/renderer/renderer.h index 9453fff899..b5fcbb5026 100644 --- a/cpp/renderer/renderer.h +++ b/cpp/renderer/renderer.h @@ -105,9 +105,13 @@ struct material { shader::Program *program; GLint uniformNormalTexture; GLint uniformMasktexture; + GLint uniformPlayerColors; GLint attributeUV; GLint attributeMaskUV; + + GLint attributePlayerCol; + GLint attributeZOrder; }; class Renderer { @@ -119,13 +123,13 @@ class Renderer { void render (); - static bool create (util::Dir const *data_dir); + static bool create (util::Dir const *data_dir, util::Dir const *asset_dir); static Renderer &get(); private: Renderer (); - bool init (util::Dir const *data_dir); + bool init (util::Dir const *data_dir, util::Dir const *asset_dir); Renderer(const Renderer ©) = delete; Renderer &operator=(const Renderer ©) = delete; diff --git a/cpp/texture.cpp b/cpp/texture.cpp index 73f5c68217..5633768d3c 100644 --- a/cpp/texture.cpp +++ b/cpp/texture.cpp @@ -151,74 +151,37 @@ void Texture::draw(coord::tile pos, int subid, Texture *alpha_texture, int alpha } void Texture::draw(coord::pixel_t x, coord::pixel_t y, bool mirrored, int subid, unsigned player, Texture *alpha_texture, int alpha_subid) { - glColor4f(1, 1, 1, 1); - //log::dbg("drawing texture at %hd, %hd", x, y); eMaterialType::Enum cType; //Use this to help transition to new renderer - - bool use_playercolors = false; - bool use_alphashader = false; struct gamedata::subtexture *mtx; - - int *pos_id, *texcoord_id, *masktexcoord_id; - + struct gamedata::subtexture *tx = this->get_subtexture(subid); + //is this texture drawn with an alpha mask? if (this->use_alpha_masking && alpha_subid >= 0 && alpha_texture != nullptr) { - alphamask_shader::program->use(); - - //bind the alpha mask texture to slot 1 - glActiveTexture(GL_TEXTURE1); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, alpha_texture->get_texture_id()); - - //get the alphamask subtexture (the blend mask!) mtx = alpha_texture->get_subtexture(alpha_subid); - pos_id = &alphamask_shader::program->pos_id; - texcoord_id = &alphamask_shader::base_coord; - masktexcoord_id = &alphamask_shader::mask_coord; - use_alphashader = true; - cType = eMaterialType::keAlphaMask; } //is this texure drawn with replaced pixels for team coloring? else if (this->use_player_color_tinting) { - teamcolor_shader::program->use(); - - //set the desired player id in the shader - glUniform1i(teamcolor_shader::player_id_var, player); - pos_id = &teamcolor_shader::program->pos_id; - texcoord_id = &teamcolor_shader::tex_coord; - use_playercolors = true; - cType = eMaterialType::keColorReplace; } //mkay, we just draw the plain texture otherwise. else { - texture_shader::program->use(); - pos_id = &texture_shader::program->pos_id; - texcoord_id = &texture_shader::tex_coord; - cType = eMaterialType::keNormal; } - glActiveTexture(GL_TEXTURE0); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, this->id); - - struct gamedata::subtexture *tx = this->get_subtexture(subid); - int left, right, top, bottom; //coordinates where the texture will be drawn on screen. bottom = y - (tx->h - tx->cy); top = bottom + tx->h; - if (not mirrored) { - left = x - tx->cx; - right = left + tx->w; - } else { + if (mirrored) { left = x + tx->cx; right = left - tx->w; + } else { + left = x - tx->cx; + right = left + tx->w; } //convert the texture boundaries to float @@ -236,72 +199,11 @@ void Texture::draw(coord::pixel_t x, coord::pixel_t y, bool mirrored, int subid, this->get_subtexture_coordinates(tx, &txl, &txr, &txt, &txb); float mtxl=0, mtxr=0, mtxt=0, mtxb=0; - if (use_alphashader) { + if (cType == eMaterialType::keAlphaMask) { alpha_texture->get_subtexture_coordinates(mtx, &mtxl, &mtxr, &mtxt, &mtxb); } - - //this array will be uploaded to the GPU. - //it contains all dynamic vertex data (position, tex coordinates, mask coordinates) - float vdata[] { - leftf, topf, - leftf, bottomf, - rightf, bottomf, - rightf, topf, - txl, txt, - txl, txb, - txr, txb, - txr, txt, - mtxl, mtxt, - mtxl, mtxb, - mtxr, mtxb, - mtxr, mtxt - }; - - //store vertex buffer data, TODO: prepare this sometime earlier. - glBindBuffer(GL_ARRAY_BUFFER, this->vertbuf); - glBufferData(GL_ARRAY_BUFFER, sizeof(vdata), vdata, GL_STREAM_DRAW); - - //enable vertex buffer and bind it to the vertex attribute - glEnableVertexAttribArray(*pos_id); - glEnableVertexAttribArray(*texcoord_id); - if (use_alphashader) { - glEnableVertexAttribArray(*masktexcoord_id); - } - - //set data types, offsets in the vdata array - glVertexAttribPointer(*pos_id, 2, GL_FLOAT, GL_FALSE, 0, (void *)(0)); - glVertexAttribPointer(*texcoord_id, 2, GL_FLOAT, GL_FALSE, 0, (void *)(sizeof(float) * 8)); - if (use_alphashader) { - glVertexAttribPointer(*masktexcoord_id, 2, GL_FLOAT, GL_FALSE, 0, (void *)(sizeof(float) * 8 * 2)); - } - - - //draw the vertex array - //glDrawArrays(GL_QUADS, 0, 4); - - //unbind the current buffer - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(*pos_id); - glDisableVertexAttribArray(*texcoord_id); - if (use_alphashader) { - glDisableVertexAttribArray(*masktexcoord_id); - } - - //disable the shaders. - if (use_playercolors) { - teamcolor_shader::program->stopusing(); - } else if (use_alphashader) { - alphamask_shader::program->stopusing(); - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); - } else { - texture_shader::program->stopusing(); - } - - glActiveTexture(GL_TEXTURE0); - glDisable(GL_TEXTURE_2D); + GLint maskID = (cType == eMaterialType::keAlphaMask) ? alpha_texture->get_texture_id() : -1; Renderer::get().submit_quad(render_quad::Create( //Position to render to @@ -314,9 +216,9 @@ void Texture::draw(coord::pixel_t x, coord::pixel_t y, bool mirrored, int subid, rect::Create(vertex2::Create(mtxl, mtxt), vertex2::Create(mtxr, mtxb)), 0, //z-value - 0), //playerID + 6), //playerID this->id, //diffuse - this->id, //Mask + maskID, //Mask cType); } From dd4f5d6050835099a5303a1a8763cff9b9b412b8 Mon Sep 17 00:00:00 2001 From: james mintram Date: Thu, 30 Oct 2014 16:03:19 +0000 Subject: [PATCH 6/9] Renderer now packs and unpacks commands for rendering - still renders one at a time --- cpp/renderer/renderer.cpp | 113 ++++++++++++++++++++++++-------------- cpp/renderer/renderer.h | 15 ++++- 2 files changed, 85 insertions(+), 43 deletions(-) diff --git a/cpp/renderer/renderer.cpp b/cpp/renderer/renderer.cpp index 8fe5da3a9d..a5965bc03e 100644 --- a/cpp/renderer/renderer.cpp +++ b/cpp/renderer/renderer.cpp @@ -136,52 +136,71 @@ void Renderer::submit_quad(render_quad const & quad, GLint diffuse, GLint mask, eMaterialType::Enum material_type) { - //Stuff data into vertex buffer //Generate a renderer key from // MaterialType(16bit) | {textureHandle(16bit) | maskHandle(16bit)} | QuadIdx (16bit) + int cIndex = render_queue.size(); - //For now we will render to quad immeadiatly (to make the transition easier) + render_token_struct pData = { + (short)material_type, + (short)diffuse, + (short)mask, + (short)cIndex + }; - // - // Pre rendering per material type - // + //Pack this into a 64bit unsigned long + render_token nToken = *((render_token*)&pData); + render_queue.push_back(nToken); + render_buffer.push_back(quad); + + //Render immediately for testing purposes + render(); + +} + +void Renderer::render() { + + //Unpack with + render_token_struct renderCommand = *((render_token_struct*)&render_queue[0]); + render_quad quad = render_buffer[0]; + + eMaterialType::Enum material_type = (eMaterialType::Enum)renderCommand.matType; + material current_material = materials[material_type]; switch (material_type) { - case eMaterialType::keNormal: { - //Render a normal texture here - break; - } - case eMaterialType::keAlphaMask: { - //bind the alpha mask texture to slot 1 - glActiveTexture(GL_TEXTURE1); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, mask); - } - default: { - //Do nothing here - break; - } + case eMaterialType::keNormal: { + //Render a normal texture here + break; + } + case eMaterialType::keAlphaMask: { + //bind the alpha mask texture to slot 1 + glActiveTexture(GL_TEXTURE1); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, renderCommand.mask); + } + default: { + //Do nothing here + break; + } } - material current_material = materials[material_type]; current_material.program->use(); glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, diffuse); + glBindTexture(GL_TEXTURE_2D, renderCommand.diffuse); //Bind vertex buffers here glBindBuffer(GL_ARRAY_BUFFER, vertbuf); glBufferData(GL_ARRAY_BUFFER, sizeof(render_quad), &quad.vertices, GL_STREAM_DRAW); - -// Need to retrieve the attributes from the shaders before we can use them here + + // Need to retrieve the attributes from the shaders before we can use them here glEnableVertexAttribArray(current_material.program->pos_id); glEnableVertexAttribArray(current_material.attributeUV); - + //set data types, offsets in the vdata array glVertexAttribPointer(current_material.program->pos_id, @@ -230,7 +249,9 @@ void Renderer::submit_quad(render_quad const & quad, (void*)offsetof(render_quad::quad_vertex, zValue)); } - //Set the masking layer here + + + //draw the vertex array glDrawArrays(GL_QUADS, 0, 4); @@ -257,27 +278,35 @@ void Renderer::submit_quad(render_quad const & quad, // Post rendering per material type // switch (material_type) { - case eMaterialType::keNormal: { - //Render a normal texture here - break; - } - case eMaterialType::keAlphaMask: { - glDisableVertexAttribArray(current_material.attributeMaskUV); - - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); - } - default: { - //Do nothing here - break; - } + case eMaterialType::keNormal: { + //Render a normal texture here + break; + } + case eMaterialType::keAlphaMask: { + glDisableVertexAttribArray(current_material.attributeMaskUV); + + glActiveTexture(GL_TEXTURE1); + glDisable(GL_TEXTURE_2D); + } + default: { + //Do nothing here + break; + } } glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); -} - -void Renderer::render() { + + + render_queue.clear(); + render_buffer.clear(); + + + + + + //--TODO + //Sort the renderlist //Build the index buffer (dependent on sorting order of quads) // Build a vector of *boundries* used when rendering diff --git a/cpp/renderer/renderer.h b/cpp/renderer/renderer.h index b5fcbb5026..81a05733e4 100644 --- a/cpp/renderer/renderer.h +++ b/cpp/renderer/renderer.h @@ -114,6 +114,8 @@ struct material { GLint attributeZOrder; }; + + class Renderer { public: void submit_quad (render_quad const & quad, @@ -137,8 +139,19 @@ class Renderer { Renderer &operator=(Renderer &&other) = delete; private: + struct render_token_struct { + short matType; + short diffuse; + short mask; + short idx; + } ; + + typedef unsigned long long render_token; + typedef std::vector render_quad_list; - render_quad_list render_queue; + typedef std::vector render_queue_list; + render_quad_list render_buffer; + render_queue_list render_queue; material materials[eMaterialType::keCount]; From 68af451d14b2ede6b7f63e4b36ad275914f9df4a Mon Sep 17 00:00:00 2001 From: james mintram Date: Fri, 31 Oct 2014 00:37:16 +0000 Subject: [PATCH 7/9] Some more good progress on the renderer - 1 vertex buffer bound once per frame Some shader tweaks made --- assets/shaders/alphamask.common.frag.glsl | 2 + assets/shaders/maptexture.frag.glsl | 1 + assets/shaders/teamcolors.frag.glsl | 2 + cpp/game_main.cpp | 4 +- cpp/renderer/renderer.cpp | 231 +++++++++++----------- 5 files changed, 122 insertions(+), 118 deletions(-) diff --git a/assets/shaders/alphamask.common.frag.glsl b/assets/shaders/alphamask.common.frag.glsl index c075317401..0f10d993d5 100644 --- a/assets/shaders/alphamask.common.frag.glsl +++ b/assets/shaders/alphamask.common.frag.glsl @@ -34,4 +34,6 @@ void main() } else { gl_FragColor = blended_pixel; } + + gl_FragDepth = 0; } diff --git a/assets/shaders/maptexture.frag.glsl b/assets/shaders/maptexture.frag.glsl index 78185f9715..3d2e7421cc 100644 --- a/assets/shaders/maptexture.frag.glsl +++ b/assets/shaders/maptexture.frag.glsl @@ -11,4 +11,5 @@ varying vec2 tex_position; void main (void) { //this sets the fragment color to the corresponding texel. gl_FragColor = texture2D(texture, tex_position); + gl_FragDepth = 0; } diff --git a/assets/shaders/teamcolors.frag.glsl b/assets/shaders/teamcolors.frag.glsl index ff6641424f..8c851ff031 100644 --- a/assets/shaders/teamcolors.frag.glsl +++ b/assets/shaders/teamcolors.frag.glsl @@ -45,4 +45,6 @@ void main() { } gl_FragColor = pixel; + gl_FragDepth = 0.2; + //gl_FragDepth = floor(gl_FragColor.a) * 0.2; } \ No newline at end of file diff --git a/cpp/game_main.cpp b/cpp/game_main.cpp index ae2efd6d82..e96bbd670f 100644 --- a/cpp/game_main.cpp +++ b/cpp/game_main.cpp @@ -555,11 +555,13 @@ bool GameMain::on_draw() { Engine &engine = Engine::get(); // draw gaben, our great and holy protector, bringer of the half-life 3. - gaben->draw(coord::camgame {0, 0}); + //gaben->draw(coord::camgame {0, 0}); // draw terrain terrain->draw(&engine); + graphics::Renderer::get().render(); + return true; } diff --git a/cpp/renderer/renderer.cpp b/cpp/renderer/renderer.cpp index a5965bc03e..5d60639fa2 100644 --- a/cpp/renderer/renderer.cpp +++ b/cpp/renderer/renderer.cpp @@ -7,7 +7,7 @@ #include "../util/dir.h" #include "../gamedata/color.gen.h" - +#include #include namespace openage { @@ -155,156 +155,153 @@ void Renderer::submit_quad(render_quad const & quad, render_buffer.push_back(quad); //Render immediately for testing purposes - render(); + //render(); } void Renderer::render() { + int quadCount = render_queue.size(); + int bufferSize = sizeof(render_quad) * quadCount; - //Unpack with - render_token_struct renderCommand = *((render_token_struct*)&render_queue[0]); - render_quad quad = render_buffer[0]; - - eMaterialType::Enum material_type = (eMaterialType::Enum)renderCommand.matType; - material current_material = materials[material_type]; + glClearDepth(0); + glDepthMask(true); - switch (material_type) { - case eMaterialType::keNormal: { - //Render a normal texture here - break; - } - case eMaterialType::keAlphaMask: { - //bind the alpha mask texture to slot 1 - glActiveTexture(GL_TEXTURE1); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, renderCommand.mask); - } - default: { - //Do nothing here - break; - } - } + + glEnable (GL_DEPTH_TEST); + glDepthFunc(GL_GEQUAL); + + glClear(GL_DEPTH_BUFFER_BIT); + glBindBuffer(GL_ARRAY_BUFFER, vertbuf); + glBufferData(GL_ARRAY_BUFFER, bufferSize, &render_buffer[0].vertices, GL_STREAM_DRAW); - current_material.program->use(); + //Sort the draw calls + std::sort(render_queue.begin(), render_queue.end()); glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, renderCommand.diffuse); - - //Bind vertex buffers here - glBindBuffer(GL_ARRAY_BUFFER, vertbuf); - glBufferData(GL_ARRAY_BUFFER, sizeof(render_quad), &quad.vertices, GL_STREAM_DRAW); - - - // Need to retrieve the attributes from the shaders before we can use them here - glEnableVertexAttribArray(current_material.program->pos_id); - glEnableVertexAttribArray(current_material.attributeUV); + for ( int cMaterial = 0; cMaterial < eMaterialType::keCount; cMaterial++) + { + + eMaterialType::Enum material_type = (eMaterialType::Enum)cMaterial; + material current_material = materials[material_type]; - //set data types, offsets in the vdata array - glVertexAttribPointer(current_material.program->pos_id, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(render_quad::quad_vertex), - (void*)offsetof(render_quad::quad_vertex, pos)); - - glVertexAttribPointer(current_material.attributeUV, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(render_quad::quad_vertex), - (void*)offsetof(render_quad::quad_vertex, uv)); - - if ( material_type == eMaterialType::keAlphaMask ) { - glEnableVertexAttribArray(current_material.attributeMaskUV); - glVertexAttribPointer(current_material.attributeMaskUV, + //if (material_type == eMaterialType::keNormal) continue; + + current_material.program->use(); + + // Need to retrieve the attributes from the shaders before we can use them here + glEnableVertexAttribArray(current_material.program->pos_id); + glEnableVertexAttribArray(current_material.attributeUV); + + //set data types, offsets in the vdata array + glVertexAttribPointer(current_material.program->pos_id, 2, GL_FLOAT, GL_FALSE, sizeof(render_quad::quad_vertex), - (void*)offsetof(render_quad::quad_vertex, maskUV)); - } - - //These checks are temporary - if ( current_material.attributePlayerCol != -1 ) - { - glEnableVertexAttribArray(current_material.attributePlayerCol); - glVertexAttribPointer(current_material.attributePlayerCol, - 1, - GL_UNSIGNED_INT, - GL_FALSE, - sizeof(render_quad::quad_vertex), - (void*)offsetof(render_quad::quad_vertex, playerID)); - } - if ( current_material.attributeZOrder != -1 ) - { - glEnableVertexAttribArray(current_material.attributeZOrder); - glVertexAttribPointer(current_material.attributeZOrder, - 1, + (void*)offsetof(render_quad::quad_vertex, pos)); + + glVertexAttribPointer(current_material.attributeUV, + 2, GL_FLOAT, GL_FALSE, sizeof(render_quad::quad_vertex), - (void*)offsetof(render_quad::quad_vertex, zValue)); - } - - - - - - //draw the vertex array - glDrawArrays(GL_QUADS, 0, 4); - - glDisableVertexAttribArray(current_material.program->pos_id); - glDisableVertexAttribArray(current_material.attributeUV); - - //These checks are temporary - if ( current_material.attributePlayerCol != -1 ) - { - glDisableVertexAttribArray(current_material.attributePlayerCol); - } - if ( current_material.attributeZOrder != -1 ) - { - glDisableVertexAttribArray(current_material.attributeZOrder); - } - - //unbind the current buffer - glBindBuffer(GL_ARRAY_BUFFER, 0); - - current_material.program->stopusing(); - - // - // Post rendering per material type - // - switch (material_type) { - case eMaterialType::keNormal: { - //Render a normal texture here - break; + (void*)offsetof(render_quad::quad_vertex, uv)); + + if ( material_type == eMaterialType::keAlphaMask ) { + glEnableVertexAttribArray(current_material.attributeMaskUV); + glVertexAttribPointer(current_material.attributeMaskUV, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, maskUV)); + + glActiveTexture(GL_TEXTURE1); + glEnable(GL_TEXTURE_2D); } - case eMaterialType::keAlphaMask: { - glDisableVertexAttribArray(current_material.attributeMaskUV); + + //These checks are temporary + if ( current_material.attributePlayerCol != -1 ) + { + glEnableVertexAttribArray(current_material.attributePlayerCol); + glVertexAttribPointer(current_material.attributePlayerCol, + 1, + GL_UNSIGNED_INT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, playerID)); + } + if ( current_material.attributeZOrder != -1 ) + { + glEnableVertexAttribArray(current_material.attributeZOrder); + glVertexAttribPointer(current_material.attributeZOrder, + 1, + GL_FLOAT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, zValue)); + } + + //Render all the quads for this material + for ( int cQuad = 0; cQuad < quadCount; cQuad++ ) + { + render_token_struct renderCommand = *((render_token_struct*)&render_queue[cQuad]); + + //Skip this quad if not correct material (temporary) + if ( (eMaterialType::Enum)renderCommand.matType != material_type ) continue; + + if ( material_type == eMaterialType::keAlphaMask ) + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, renderCommand.mask); + } + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, renderCommand.diffuse); + + //draw the vertex array + glDrawArrays(GL_QUADS, renderCommand.idx * 4, 4); + } + + + glDisableVertexAttribArray(current_material.program->pos_id); + glDisableVertexAttribArray(current_material.attributeUV); + + //These checks are temporary + if ( current_material.attributePlayerCol != -1 ) + { + glDisableVertexAttribArray(current_material.attributePlayerCol); + } + if ( current_material.attributeZOrder != -1 ) + { + glDisableVertexAttribArray(current_material.attributeZOrder); + } + + if ( material_type == eMaterialType::keAlphaMask) { + glDisableVertexAttribArray(current_material.attributeMaskUV); glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); } - default: { - //Do nothing here - break; - } + + current_material.program->stopusing(); } + //unbind the current buffer + glBindBuffer(GL_ARRAY_BUFFER, 0); glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); + glDisable (GL_DEPTH_TEST); + glDepthMask(false); + + glClear(GL_DEPTH_BUFFER_BIT); render_queue.clear(); render_buffer.clear(); - - - - //--TODO //Sort the renderlist From ca97f0b7181dc066de4934cad8e163fb043cb89b Mon Sep 17 00:00:00 2001 From: james mintram Date: Fri, 31 Oct 2014 11:22:28 +0000 Subject: [PATCH 8/9] Added layers to renderer Improved efficiency some ore --- cpp/renderer/renderer.cpp | 289 +++++++++++++++++++++----------------- cpp/renderer/renderer.h | 11 +- cpp/texture.cpp | 6 + 3 files changed, 175 insertions(+), 131 deletions(-) diff --git a/cpp/renderer/renderer.cpp b/cpp/renderer/renderer.cpp index 5d60639fa2..5a6f4fc4ed 100644 --- a/cpp/renderer/renderer.cpp +++ b/cpp/renderer/renderer.cpp @@ -135,6 +135,7 @@ bool Renderer::init(util::Dir const *data_dir, util::Dir const *asset_dir) { void Renderer::submit_quad(render_quad const & quad, GLint diffuse, GLint mask, + unsigned char layer, eMaterialType::Enum material_type) { //Generate a renderer key from @@ -143,10 +144,11 @@ void Renderer::submit_quad(render_quad const & quad, int cIndex = render_queue.size(); render_token_struct pData = { - (short)material_type, - (short)diffuse, + (short)cIndex, (short)mask, - (short)cIndex + (short)diffuse, + (unsigned char)material_type, + layer, }; //Pack this into a 64bit unsigned long @@ -158,7 +160,94 @@ void Renderer::submit_quad(render_quad const & quad, //render(); } + +void Renderer::apply_material (eMaterialType::Enum material_type) { + material current_material = materials[material_type]; + + //if (material_type == eMaterialType::keNormal) continue; + + current_material.program->use(); + + // Need to retrieve the attributes from the shaders before we can use them here + glEnableVertexAttribArray(current_material.program->pos_id); + glEnableVertexAttribArray(current_material.attributeUV); + + //set data types, offsets in the vdata array + glVertexAttribPointer(current_material.program->pos_id, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, pos)); + + glVertexAttribPointer(current_material.attributeUV, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, uv)); + + if ( material_type == eMaterialType::keAlphaMask ) { + glEnableVertexAttribArray(current_material.attributeMaskUV); + glVertexAttribPointer(current_material.attributeMaskUV, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, maskUV)); + + glActiveTexture(GL_TEXTURE1); + glEnable(GL_TEXTURE_2D); + } + + //These checks are temporary + if ( current_material.attributePlayerCol != -1 ) + { + glEnableVertexAttribArray(current_material.attributePlayerCol); + glVertexAttribPointer(current_material.attributePlayerCol, + 1, + GL_UNSIGNED_INT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, playerID)); + } + if ( current_material.attributeZOrder != -1 ) + { + glEnableVertexAttribArray(current_material.attributeZOrder); + glVertexAttribPointer(current_material.attributeZOrder, + 1, + GL_FLOAT, + GL_FALSE, + sizeof(render_quad::quad_vertex), + (void*)offsetof(render_quad::quad_vertex, zValue)); + } +} +void Renderer::disable_material (eMaterialType::Enum material_type){ + material current_material = materials[material_type]; + + glDisableVertexAttribArray(current_material.program->pos_id); + glDisableVertexAttribArray(current_material.attributeUV); + + //These checks are temporary + if ( current_material.attributePlayerCol != -1 ) + { + glDisableVertexAttribArray(current_material.attributePlayerCol); + } + if ( current_material.attributeZOrder != -1 ) + { + glDisableVertexAttribArray(current_material.attributeZOrder); + } + + if ( material_type == eMaterialType::keAlphaMask) { + glDisableVertexAttribArray(current_material.attributeMaskUV); + glActiveTexture(GL_TEXTURE1); + glDisable(GL_TEXTURE_2D); + } + + current_material.program->stopusing(); +} + void Renderer::render() { int quadCount = render_queue.size(); int bufferSize = sizeof(render_quad) * quadCount; @@ -169,8 +258,6 @@ void Renderer::render() { glEnable (GL_DEPTH_TEST); glDepthFunc(GL_GEQUAL); - - glClear(GL_DEPTH_BUFFER_BIT); glBindBuffer(GL_ARRAY_BUFFER, vertbuf); glBufferData(GL_ARRAY_BUFFER, bufferSize, &render_buffer[0].vertices, GL_STREAM_DRAW); @@ -178,116 +265,84 @@ void Renderer::render() { //Sort the draw calls std::sort(render_queue.begin(), render_queue.end()); + render_token_struct lastCommand = *((render_token_struct*)&render_queue[render_queue.size()-1]); + unsigned char maxLayer = lastCommand.layer; + glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); - - for ( int cMaterial = 0; cMaterial < eMaterialType::keCount; cMaterial++) + + int cQuad = 0; + for ( int cLayer = 0; cLayer <= maxLayer; cLayer++) { - - eMaterialType::Enum material_type = (eMaterialType::Enum)cMaterial; - material current_material = materials[material_type]; - - //if (material_type == eMaterialType::keNormal) continue; - - current_material.program->use(); - - // Need to retrieve the attributes from the shaders before we can use them here - glEnableVertexAttribArray(current_material.program->pos_id); - glEnableVertexAttribArray(current_material.attributeUV); - - //set data types, offsets in the vdata array - glVertexAttribPointer(current_material.program->pos_id, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(render_quad::quad_vertex), - (void*)offsetof(render_quad::quad_vertex, pos)); - - glVertexAttribPointer(current_material.attributeUV, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(render_quad::quad_vertex), - (void*)offsetof(render_quad::quad_vertex, uv)); - - if ( material_type == eMaterialType::keAlphaMask ) { - glEnableVertexAttribArray(current_material.attributeMaskUV); - glVertexAttribPointer(current_material.attributeMaskUV, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(render_quad::quad_vertex), - (void*)offsetof(render_quad::quad_vertex, maskUV)); - - glActiveTexture(GL_TEXTURE1); - glEnable(GL_TEXTURE_2D); - } - - //These checks are temporary - if ( current_material.attributePlayerCol != -1 ) - { - glEnableVertexAttribArray(current_material.attributePlayerCol); - glVertexAttribPointer(current_material.attributePlayerCol, - 1, - GL_UNSIGNED_INT, - GL_FALSE, - sizeof(render_quad::quad_vertex), - (void*)offsetof(render_quad::quad_vertex, playerID)); - } - if ( current_material.attributeZOrder != -1 ) - { - glEnableVertexAttribArray(current_material.attributeZOrder); - glVertexAttribPointer(current_material.attributeZOrder, - 1, - GL_FLOAT, - GL_FALSE, - sizeof(render_quad::quad_vertex), - (void*)offsetof(render_quad::quad_vertex, zValue)); - } - - //Render all the quads for this material - for ( int cQuad = 0; cQuad < quadCount; cQuad++ ) - { - render_token_struct renderCommand = *((render_token_struct*)&render_queue[cQuad]); + glClear(GL_DEPTH_BUFFER_BIT); - //Skip this quad if not correct material (temporary) - if ( (eMaterialType::Enum)renderCommand.matType != material_type ) continue; - - if ( material_type == eMaterialType::keAlphaMask ) + for ( int cMaterial = 0; cMaterial < eMaterialType::keCount; cMaterial++) + { + eMaterialType::Enum material_type = (eMaterialType::Enum)cMaterial; + apply_material(material_type); + + //Render all the quads for this material + while ( cQuad < quadCount ) { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, renderCommand.mask); + render_token_struct renderCommand = *((render_token_struct*)&render_queue[cQuad]); + if ( (eMaterialType::Enum)renderCommand.matType != material_type ) break; + + if ( material_type == eMaterialType::keAlphaMask ) + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, renderCommand.mask); + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, renderCommand.diffuse); + + //draw the vertex array + glDrawArrays(GL_QUADS, renderCommand.idx * 4, 4); + + cQuad++; } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, renderCommand.diffuse); - - //draw the vertex array - glDrawArrays(GL_QUADS, renderCommand.idx * 4, 4); - } - - - glDisableVertexAttribArray(current_material.program->pos_id); - glDisableVertexAttribArray(current_material.attributeUV); - - //These checks are temporary - if ( current_material.attributePlayerCol != -1 ) - { - glDisableVertexAttribArray(current_material.attributePlayerCol); - } - if ( current_material.attributeZOrder != -1 ) - { - glDisableVertexAttribArray(current_material.attributeZOrder); - } - - if ( material_type == eMaterialType::keAlphaMask) { - glDisableVertexAttribArray(current_material.attributeMaskUV); - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); + disable_material(material_type); } - - current_material.program->stopusing(); + } + // + +// for ( int cLayer = 0; cLayer <= maxLayer; cLayer++) +// { +// glClear(GL_DEPTH_BUFFER_BIT); +// +// for ( int cMaterial = 0; cMaterial < eMaterialType::keCount; cMaterial++) +// { +// +// eMaterialType::Enum material_type = (eMaterialType::Enum)cMaterial; +// apply_material(material_type); +// +// //Render all the quads for this material +// for ( int cQuad = 0; cQuad < quadCount; cQuad++ ) +// { +// render_token_struct renderCommand = *((render_token_struct*)&render_queue[cQuad]); +// +// //Skip this quad if not correct material (temporary) +// if ( (eMaterialType::Enum)renderCommand.matType != material_type ) continue; +// if (renderCommand.layer != cLayer ) continue; +// +// if ( material_type == eMaterialType::keAlphaMask ) +// { +// glActiveTexture(GL_TEXTURE1); +// glBindTexture(GL_TEXTURE_2D, renderCommand.mask); +// } +// +// glActiveTexture(GL_TEXTURE0); +// glBindTexture(GL_TEXTURE_2D, renderCommand.diffuse); +// +// //draw the vertex array +// glDrawArrays(GL_QUADS, renderCommand.idx * 4, 4); +// } +// +// disable_material(material_type); +// } +// } //unbind the current buffer glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -301,28 +356,6 @@ void Renderer::render() { render_queue.clear(); render_buffer.clear(); - - //--TODO - - //Sort the renderlist - //Build the index buffer (dependent on sorting order of quads) - // Build a vector of *boundries* used when rendering - - - //Bind vertex buffer - //Bind index buffer - - - //Clear the depth buffer - //Enable depth test - //Enable depth write - - - //Foreach materialtype - // bind shader - - // Foreach item in boundries - // drawelements using boundry information } } diff --git a/cpp/renderer/renderer.h b/cpp/renderer/renderer.h index 81a05733e4..234ae5add3 100644 --- a/cpp/renderer/renderer.h +++ b/cpp/renderer/renderer.h @@ -121,6 +121,7 @@ class Renderer { void submit_quad (render_quad const & quad, GLint diffuse, GLint mask, + unsigned char layer, eMaterialType::Enum material_type); void render (); @@ -133,6 +134,9 @@ class Renderer { Renderer (); bool init (util::Dir const *data_dir, util::Dir const *asset_dir); + void apply_material (eMaterialType::Enum material_type); + void disable_material (eMaterialType::Enum material_type); + Renderer(const Renderer ©) = delete; Renderer &operator=(const Renderer ©) = delete; Renderer(Renderer &&other) = delete; @@ -140,10 +144,11 @@ class Renderer { private: struct render_token_struct { - short matType; - short diffuse; - short mask; short idx; + short mask; + short diffuse; + unsigned char matType; + unsigned char layer; } ; typedef unsigned long long render_token; diff --git a/cpp/texture.cpp b/cpp/texture.cpp index 5633768d3c..159bfd0556 100644 --- a/cpp/texture.cpp +++ b/cpp/texture.cpp @@ -156,17 +156,22 @@ void Texture::draw(coord::pixel_t x, coord::pixel_t y, bool mirrored, int subid, struct gamedata::subtexture *mtx; struct gamedata::subtexture *tx = this->get_subtexture(subid); + int cLayer = 0; + //is this texture drawn with an alpha mask? if (this->use_alpha_masking && alpha_subid >= 0 && alpha_texture != nullptr) { + cLayer = 0; mtx = alpha_texture->get_subtexture(alpha_subid); cType = eMaterialType::keAlphaMask; } //is this texure drawn with replaced pixels for team coloring? else if (this->use_player_color_tinting) { + cLayer = 1; cType = eMaterialType::keColorReplace; } //mkay, we just draw the plain texture otherwise. else { + cLayer = 0; cType = eMaterialType::keNormal; } @@ -219,6 +224,7 @@ void Texture::draw(coord::pixel_t x, coord::pixel_t y, bool mirrored, int subid, 6), //playerID this->id, //diffuse maskID, //Mask + cLayer, //Layer cType); } From d671608b792a8858436cf8eb442101d798907254 Mon Sep 17 00:00:00 2001 From: james mintram Date: Fri, 31 Oct 2014 22:10:11 +0000 Subject: [PATCH 9/9] Renderer dynamically batches draw calls by layer, material, then textures --- cpp/renderer/renderer.cpp | 100 ++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/cpp/renderer/renderer.cpp b/cpp/renderer/renderer.cpp index 5a6f4fc4ed..7684dfb35d 100644 --- a/cpp/renderer/renderer.cpp +++ b/cpp/renderer/renderer.cpp @@ -248,6 +248,28 @@ void Renderer::disable_material (eMaterialType::Enum material_type){ current_material.program->stopusing(); } +void renderBuffer (std::vector &idxBuffer, + eMaterialType::Enum material_type, + GLint diffuse, + GLint mask) +{ + //Render out + if ( material_type == eMaterialType::keAlphaMask ) + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, mask); + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, diffuse); + + //draw the vertex array + glDrawElements(GL_QUADS, idxBuffer.size(), GL_UNSIGNED_SHORT, &idxBuffer[0]); + //glDrawArrays(GL_QUADS, renderCommand.idx * 4, 4); + + idxBuffer.clear(); +} + void Renderer::render() { int quadCount = render_queue.size(); int bufferSize = sizeof(render_quad) * quadCount; @@ -271,6 +293,8 @@ void Renderer::render() { glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); + std::vector indexBuffer; + int cQuad = 0; for ( int cLayer = 0; cLayer <= maxLayer; cLayer++) { @@ -282,67 +306,51 @@ void Renderer::render() { apply_material(material_type); //Render all the quads for this material - while ( cQuad < quadCount ) + while ( true ) { render_token_struct renderCommand = *((render_token_struct*)&render_queue[cQuad]); - if ( (eMaterialType::Enum)renderCommand.matType != material_type ) break; + GLint textureCombo = *((GLint*)&renderCommand.diffuse); - if ( material_type == eMaterialType::keAlphaMask ) + if ( (eMaterialType::Enum)renderCommand.matType != material_type ) { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, renderCommand.mask); + //printf ("Batching %lu on material change\n", indexBuffer.size()); + renderBuffer(indexBuffer, material_type, renderCommand.diffuse, renderCommand.mask); + break; } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, renderCommand.diffuse); + indexBuffer.push_back((renderCommand.idx * 4)); + indexBuffer.push_back((renderCommand.idx * 4) +1); + indexBuffer.push_back((renderCommand.idx * 4) +2); + indexBuffer.push_back((renderCommand.idx * 4) +3); - //draw the vertex array - glDrawArrays(GL_QUADS, renderCommand.idx * 4, 4); cQuad++; + if ( cQuad >= quadCount) + { + //printf ("Completing render %lu\n", indexBuffer.size()); + renderBuffer(indexBuffer, material_type, renderCommand.diffuse, renderCommand.mask); + break; + } + + render_token_struct nextRenderCommand = *((render_token_struct*)&render_queue[cQuad]); + GLint nextTextureCombo = *((GLint*)&nextRenderCommand.diffuse); + + //Check for texture change + if ((eMaterialType::Enum)nextRenderCommand.matType != material_type + || nextTextureCombo != textureCombo) + { + //printf ("Batching %lu on texture change\n", indexBuffer.size()); + renderBuffer(indexBuffer, material_type, renderCommand.diffuse, renderCommand.mask); + //renderBuffer(indexBuffer, material_type, renderCommand.diffuse, renderCommand.diffuse); + } } + //Render + disable_material(material_type); } } - // - -// for ( int cLayer = 0; cLayer <= maxLayer; cLayer++) -// { -// glClear(GL_DEPTH_BUFFER_BIT); -// -// for ( int cMaterial = 0; cMaterial < eMaterialType::keCount; cMaterial++) -// { -// -// eMaterialType::Enum material_type = (eMaterialType::Enum)cMaterial; -// apply_material(material_type); -// -// //Render all the quads for this material -// for ( int cQuad = 0; cQuad < quadCount; cQuad++ ) -// { -// render_token_struct renderCommand = *((render_token_struct*)&render_queue[cQuad]); -// -// //Skip this quad if not correct material (temporary) -// if ( (eMaterialType::Enum)renderCommand.matType != material_type ) continue; -// if (renderCommand.layer != cLayer ) continue; -// -// if ( material_type == eMaterialType::keAlphaMask ) -// { -// glActiveTexture(GL_TEXTURE1); -// glBindTexture(GL_TEXTURE_2D, renderCommand.mask); -// } -// -// glActiveTexture(GL_TEXTURE0); -// glBindTexture(GL_TEXTURE_2D, renderCommand.diffuse); -// -// //draw the vertex array -// glDrawArrays(GL_QUADS, renderCommand.idx * 4, 4); -// } -// -// disable_material(material_type); -// } -// } //unbind the current buffer glBindBuffer(GL_ARRAY_BUFFER, 0);