|
|
@@ -24,1008 +24,577 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
*/
|
|
|
|
|
|
-#include <GL/glew.h>
|
|
|
-#include <algorithm>
|
|
|
-
|
|
|
#include "Config.h"
|
|
|
|
|
|
+#if defined(LINUX) || defined(WINDOWS)
|
|
|
+ #include <GL/glew.h>
|
|
|
+#elif defined(ANDROID)
|
|
|
+ #include <GLES2/gl2.h>
|
|
|
+#else
|
|
|
+ #error "Oops, wrong platform"
|
|
|
+#endif
|
|
|
+
|
|
|
+#include <algorithm>
|
|
|
#include "Allocator.h"
|
|
|
#include "Assert.h"
|
|
|
#include "Types.h"
|
|
|
#include "GLRenderer.h"
|
|
|
-#include "GLUtils.h"
|
|
|
#include "Log.h"
|
|
|
-#include "Material.h"
|
|
|
-#include "Vec2.h"
|
|
|
-#include "Vec3.h"
|
|
|
#include "Vec4.h"
|
|
|
#include "Mat3.h"
|
|
|
#include "Mat4.h"
|
|
|
#include "Device.h"
|
|
|
+#include "Hash.h"
|
|
|
+#include "StringUtils.h"
|
|
|
|
|
|
namespace crown
|
|
|
{
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-static const char* gl_error_to_string(GLenum error)
|
|
|
+const GLenum PRIMITIVE_TYPE_TABLE[] =
|
|
|
{
|
|
|
- switch (error)
|
|
|
- {
|
|
|
- case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
|
|
|
- case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
|
|
|
- case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
|
|
|
- case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
|
|
|
- default: return "UNKNOWN_GL_ERROR";
|
|
|
- }
|
|
|
-}
|
|
|
+ GL_TRIANGLES,
|
|
|
+ GL_POINTS,
|
|
|
+ GL_LINES
|
|
|
+};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
|
|
|
- #define GL_CHECK(function)\
|
|
|
- function;\
|
|
|
- do { GLenum error; CE_ASSERT((error = glGetError()) == GL_NO_ERROR,\
|
|
|
- "OpenGL error: %s", gl_error_to_string(error)); } while (0)
|
|
|
-#else
|
|
|
- #define GL_CHECK(function)\
|
|
|
- function;
|
|
|
-#endif
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-GLRenderer::GLRenderer() :
|
|
|
- m_max_texture_size(0),
|
|
|
- m_max_texture_units(0),
|
|
|
- m_max_vertex_indices(0),
|
|
|
- m_max_vertex_vertices(0),
|
|
|
- m_max_anisotropy(0.0f),
|
|
|
-
|
|
|
- m_ambient_light_color(Color4::GRAY),
|
|
|
-
|
|
|
- m_textures_id_table(m_allocator, MAX_TEXTURES),
|
|
|
- m_active_texture_unit(0),
|
|
|
-
|
|
|
- m_vertex_buffers_id_table(m_allocator, MAX_VERTEX_BUFFERS),
|
|
|
- m_index_buffers_id_table(m_allocator, MAX_INDEX_BUFFERS),
|
|
|
- m_vertex_shaders_id_table(m_allocator, MAX_VERTEX_SHADERS),
|
|
|
- m_pixel_shaders_id_table(m_allocator, MAX_PIXEL_SHADERS),
|
|
|
- m_gpu_programs_id_table(m_allocator, 128)
|
|
|
- //m_render_buffers_id_table(m_allocator, MAX_RENDER_BUFFERS)
|
|
|
+const GLenum TEXTURE_MIN_FILTER_TABLE[] =
|
|
|
{
|
|
|
- m_min_max_point_size[0] = 0.0f;
|
|
|
- m_min_max_point_size[1] = 0.0f;
|
|
|
- m_min_max_line_width[0] = 0.0f;
|
|
|
- m_min_max_line_width[1] = 0.0f;
|
|
|
-
|
|
|
- // Initialize viewport and scissor
|
|
|
- m_viewport[0] = 0;
|
|
|
- m_viewport[1] = 0;
|
|
|
- m_viewport[2] = 0;
|
|
|
- m_viewport[3] = 0;
|
|
|
-
|
|
|
- m_scissor[0] = 0;
|
|
|
- m_scissor[1] = 0;
|
|
|
- m_scissor[2] = 0;
|
|
|
- m_scissor[3] = 0;
|
|
|
-
|
|
|
- // Initialize texture units
|
|
|
- for (uint32_t i = 0; i < MAX_TEXTURE_UNITS; i++)
|
|
|
- {
|
|
|
- m_texture_unit[i] = 0;
|
|
|
- m_texture_unit_target[i] = GL_TEXTURE_2D;
|
|
|
- }
|
|
|
-
|
|
|
- // Initialize the matrices
|
|
|
- for (uint32_t i = 0; i < MT_COUNT; i++)
|
|
|
- {
|
|
|
- m_matrix[i].load_identity();
|
|
|
- }
|
|
|
-
|
|
|
- m_model_view_matrix.load_identity();
|
|
|
- m_model_view_projection_matrix.load_identity();
|
|
|
-}
|
|
|
+ 0, // Unused
|
|
|
+ GL_NEAREST,
|
|
|
+ GL_LINEAR,
|
|
|
+ GL_NEAREST_MIPMAP_LINEAR,
|
|
|
+ GL_LINEAR_MIPMAP_LINEAR
|
|
|
+};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-GLRenderer::~GLRenderer()
|
|
|
+const GLenum TEXTURE_MAG_FILTER_TABLE[] =
|
|
|
{
|
|
|
-}
|
|
|
+ 0, // Unused
|
|
|
+ GL_NEAREST,
|
|
|
+ GL_LINEAR,
|
|
|
+ GL_LINEAR,
|
|
|
+ GL_LINEAR
|
|
|
+};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::init()
|
|
|
+const GLenum TEXTURE_WRAP_TABLE[] =
|
|
|
{
|
|
|
- m_context.create_context();
|
|
|
-
|
|
|
- GLenum err = glewInit();
|
|
|
- CE_ASSERT(err == GLEW_OK, "Failed to initialize GLEW");
|
|
|
-
|
|
|
- GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_max_texture_size));
|
|
|
- GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &m_max_texture_units));
|
|
|
- GL_CHECK(glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &m_max_vertex_indices));
|
|
|
- GL_CHECK(glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &m_max_vertex_vertices));
|
|
|
+ 0, // Unused
|
|
|
+ GL_CLAMP_TO_EDGE,
|
|
|
+ GL_REPEAT
|
|
|
+};
|
|
|
|
|
|
- // Check for anisotropic filter support
|
|
|
- if (GLEW_EXT_texture_filter_anisotropic)
|
|
|
- {
|
|
|
- GL_CHECK(glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &m_max_anisotropy));
|
|
|
- }
|
|
|
-
|
|
|
- GL_CHECK(glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, &m_min_max_point_size[0]));
|
|
|
- GL_CHECK(glGetFloatv(GL_LINE_WIDTH_RANGE, &m_min_max_line_width[0]));
|
|
|
-
|
|
|
- Log::i("OpenGL Vendor\t: %s", glGetString(GL_VENDOR));
|
|
|
- Log::i("OpenGL Renderer\t: %s", glGetString(GL_RENDERER));
|
|
|
- Log::i("OpenGL Version\t: %s", glGetString(GL_VERSION));
|
|
|
-
|
|
|
- Log::d("Min Point Size\t: %f", m_min_max_point_size[0]);
|
|
|
- Log::d("Max Point Size\t: %f", m_min_max_point_size[1]);
|
|
|
- Log::d("Min Line Width\t: %f", m_min_max_line_width[0]);
|
|
|
- Log::d("Max Line Width\t: %f", m_min_max_line_width[1]);
|
|
|
- Log::d("Max Texture Size\t: %dx%d", m_max_texture_size, m_max_texture_size);
|
|
|
- Log::d("Max Texture Units\t: %d", m_max_texture_units);
|
|
|
- Log::d("Max Vertex Indices\t: %d", m_max_vertex_indices);
|
|
|
- Log::d("Max Vertex Vertices\t: %d", m_max_vertex_vertices);
|
|
|
- Log::d("Max Anisotropy\t: %f", m_max_anisotropy);
|
|
|
-
|
|
|
- GL_CHECK(glDisable(GL_TEXTURE_2D));
|
|
|
-
|
|
|
- GL_CHECK(glDisable(GL_BLEND));
|
|
|
- GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
|
|
- GL_CHECK(glBlendEquation(GL_FUNC_ADD));
|
|
|
-
|
|
|
- GL_CHECK(glFrontFace(GL_CCW));
|
|
|
- GL_CHECK(glEnable(GL_CULL_FACE));
|
|
|
- GL_CHECK(glShadeModel(GL_SMOOTH));
|
|
|
-
|
|
|
- // Set the default framebuffer clear color
|
|
|
- GL_CHECK(glClearColor(0.5f, 0.5f, 0.5f, 0.5f));
|
|
|
-
|
|
|
- // Enable depth test
|
|
|
- GL_CHECK(glEnable(GL_DEPTH_TEST));
|
|
|
- GL_CHECK(glDepthFunc(GL_LEQUAL));
|
|
|
- GL_CHECK(glClearDepth(1.0));
|
|
|
-
|
|
|
- // Enable scissor test
|
|
|
- GL_CHECK(glEnable(GL_SCISSOR_TEST));
|
|
|
-
|
|
|
- // Disable dithering
|
|
|
- GL_CHECK(glDisable(GL_DITHER));
|
|
|
-
|
|
|
- // Point sprites enabled by default
|
|
|
- GL_CHECK(glEnable(GL_POINT_SPRITE));
|
|
|
- GL_CHECK(glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE));
|
|
|
-
|
|
|
- Log::i("OpenGL Renderer initialized.");
|
|
|
-
|
|
|
- load_default_shaders();
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::shutdown()
|
|
|
+// Keep in sync with ShaderAttrib
|
|
|
+const char* const SHADER_ATTRIB_NAMES[ATTRIB_COUNT] =
|
|
|
{
|
|
|
- unload_default_shaders();
|
|
|
-
|
|
|
- m_context.destroy_context();
|
|
|
-}
|
|
|
+ "a_position",
|
|
|
+ "a_normal",
|
|
|
+ "a_color",
|
|
|
+ "a_tex_coord0",
|
|
|
+ "a_tex_coord1",
|
|
|
+ "a_tex_coord2",
|
|
|
+ "a_tex_coord3"
|
|
|
+};
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-VertexBufferId GLRenderer::create_vertex_buffer(size_t count, VertexFormat format, const void* vertices)
|
|
|
+const char* const SHADER_UNIFORM_NAMES[] =
|
|
|
{
|
|
|
- const VertexBufferId id = m_vertex_buffers_id_table.create();
|
|
|
-
|
|
|
- VertexBuffer& buffer = m_vertex_buffers[id.index];
|
|
|
+ "u_view",
|
|
|
+ "u_model",
|
|
|
+ "u_model_view",
|
|
|
+ "u_model_view_projection",
|
|
|
+ "u_time_since_start"
|
|
|
+};
|
|
|
|
|
|
- GL_CHECK(glGenBuffers(1, &buffer.gl_object));
|
|
|
-
|
|
|
- GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, buffer.gl_object));
|
|
|
- GL_CHECK(glBufferData(GL_ARRAY_BUFFER, count * Vertex::bytes_per_vertex(format), vertices, GL_STATIC_DRAW));
|
|
|
-
|
|
|
- buffer.count = count;
|
|
|
- buffer.format = format;
|
|
|
-
|
|
|
- return id;
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-VertexBufferId GLRenderer::create_dynamic_vertex_buffer(size_t count, VertexFormat format, const void* vertices)
|
|
|
-{
|
|
|
- const VertexBufferId id = m_vertex_buffers_id_table.create();
|
|
|
-
|
|
|
- VertexBuffer& buffer = m_vertex_buffers[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glGenBuffers(1, &buffer.gl_object));
|
|
|
-
|
|
|
- GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, buffer.gl_object));
|
|
|
- GL_CHECK(glBufferData(GL_ARRAY_BUFFER, count * Vertex::bytes_per_vertex(format), vertices, GL_STREAM_DRAW));
|
|
|
-
|
|
|
- buffer.count = count;
|
|
|
- buffer.format = format;
|
|
|
-
|
|
|
- return id;
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::update_vertex_buffer(VertexBufferId id, size_t offset, size_t count, const void* vertices)
|
|
|
-{
|
|
|
- CE_ASSERT(m_vertex_buffers_id_table.has(id), "Vertex buffer does not exist");
|
|
|
-
|
|
|
- VertexBuffer& buffer = m_vertex_buffers[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, buffer.gl_object));
|
|
|
- GL_CHECK(glBufferSubData(GL_ARRAY_BUFFER, offset * Vertex::bytes_per_vertex(buffer.format),
|
|
|
- count * Vertex::bytes_per_vertex(buffer.format), vertices));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::destroy_vertex_buffer(VertexBufferId id)
|
|
|
-{
|
|
|
- CE_ASSERT(m_vertex_buffers_id_table.has(id), "Vertex buffer does not exist");
|
|
|
-
|
|
|
- VertexBuffer& buffer = m_vertex_buffers[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glDeleteBuffers(1, &buffer.gl_object));
|
|
|
-
|
|
|
- m_vertex_buffers_id_table.destroy(id);
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-IndexBufferId GLRenderer::create_index_buffer(size_t count, const void* indices)
|
|
|
-{
|
|
|
- const IndexBufferId id = m_index_buffers_id_table.create();
|
|
|
-
|
|
|
- IndexBuffer& buffer = m_index_buffers[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glGenBuffers(1, &buffer.gl_object));
|
|
|
-
|
|
|
- GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.gl_object));
|
|
|
- GL_CHECK(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(GLushort), indices, GL_STATIC_DRAW));
|
|
|
-
|
|
|
- buffer.index_count = count;
|
|
|
-
|
|
|
- return id;
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::destroy_index_buffer(IndexBufferId id)
|
|
|
+const size_t UNIFORM_SIZE_TABLE[UNIFORM_END] =
|
|
|
{
|
|
|
- CE_ASSERT(m_index_buffers_id_table.has(id), "Index buffer does not exist");
|
|
|
-
|
|
|
- IndexBuffer& buffer = m_index_buffers[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glDeleteBuffers(1, &buffer.gl_object));
|
|
|
+ sizeof(int32_t) * 1,
|
|
|
+ sizeof(int32_t) * 2,
|
|
|
+ sizeof(int32_t) * 3,
|
|
|
+ sizeof(int32_t) * 4,
|
|
|
+ sizeof(float) * 1,
|
|
|
+ sizeof(float) * 2,
|
|
|
+ sizeof(float) * 3,
|
|
|
+ sizeof(float) * 4,
|
|
|
+ sizeof(float) * 9,
|
|
|
+ sizeof(float) * 16
|
|
|
+};
|
|
|
|
|
|
- m_index_buffers_id_table.destroy(id);
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-TextureId GLRenderer::create_texture(uint32_t width, uint32_t height, PixelFormat format, const void* data)
|
|
|
+ShaderUniform name_to_stock_uniform(const char* uniform)
|
|
|
{
|
|
|
- const TextureId id = m_textures_id_table.create();
|
|
|
-
|
|
|
- Texture& gl_texture = m_textures[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glGenTextures(1, &gl_texture.gl_object));
|
|
|
-
|
|
|
- GL_CHECK(glBindTexture(GL_TEXTURE_2D, gl_texture.gl_object));
|
|
|
-
|
|
|
- GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE));
|
|
|
-
|
|
|
- // FIXME
|
|
|
- GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
|
|
- GL::pixel_format(format), GL_UNSIGNED_BYTE, data));
|
|
|
-
|
|
|
- gl_texture.format = format;
|
|
|
-
|
|
|
- return id;
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::update_texture(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data)
|
|
|
-{
|
|
|
- CE_ASSERT(m_textures_id_table.has(id), "Texture does not exist");
|
|
|
-
|
|
|
- Texture& gl_texture = m_textures[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glBindTexture(GL_TEXTURE_2D, gl_texture.gl_object));
|
|
|
-
|
|
|
- GL_CHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL::pixel_format(gl_texture.format),
|
|
|
- GL_UNSIGNED_BYTE, data));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::destroy_texture(TextureId id)
|
|
|
-{
|
|
|
- CE_ASSERT(m_textures_id_table.has(id), "Texture does not exist");
|
|
|
-
|
|
|
- Texture& gl_texture = m_textures[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glDeleteTextures(1, &gl_texture.gl_object));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-VertexShaderId GLRenderer::create_vertex_shader(const char* program)
|
|
|
-{
|
|
|
- CE_ASSERT(program != NULL, "Program must be != NULL");
|
|
|
-
|
|
|
- const VertexShaderId& id = m_vertex_shaders_id_table.create();
|
|
|
-
|
|
|
- VertexShader& gl_shader = m_vertex_shaders[id.index];
|
|
|
-
|
|
|
- gl_shader.gl_object = GL_CHECK(glCreateShader(GL_VERTEX_SHADER));
|
|
|
-
|
|
|
- GL_CHECK(glShaderSource(gl_shader.gl_object, 1, &program, NULL));
|
|
|
-
|
|
|
- GL_CHECK(glCompileShader(gl_shader.gl_object));
|
|
|
-
|
|
|
- GLint success;
|
|
|
- GL_CHECK(glGetShaderiv(gl_shader.gl_object, GL_COMPILE_STATUS, &success));
|
|
|
-
|
|
|
- if (!success)
|
|
|
+ for (uint8_t i = 0; i < UNIFORM_COUNT; i++)
|
|
|
{
|
|
|
- GLchar info_log[256];
|
|
|
-
|
|
|
- GL_CHECK(glGetShaderInfoLog(gl_shader.gl_object, 256, NULL, info_log));
|
|
|
-
|
|
|
- Log::e("Vertex shader compilation failed.");
|
|
|
- Log::e("Log: %s", info_log);
|
|
|
- CE_ASSERT(0, "");
|
|
|
+ if (string::strcmp(uniform, SHADER_UNIFORM_NAMES[i]) == 0)
|
|
|
+ {
|
|
|
+ return (ShaderUniform) i;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- return id;
|
|
|
+ return UNIFORM_COUNT;
|
|
|
}
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::destroy_vertex_shader(VertexShaderId id)
|
|
|
+/// OpenGL renderer
|
|
|
+class RendererImplementation
|
|
|
{
|
|
|
- CE_ASSERT(m_vertex_shaders_id_table.has(id), "Vertex shader does not exist");
|
|
|
-
|
|
|
- VertexShader& gl_shader = m_vertex_shaders[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glDeleteShader(gl_shader.gl_object));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-PixelShaderId GLRenderer::create_pixel_shader(const char* program)
|
|
|
-{
|
|
|
- CE_ASSERT(program != NULL, "Program must be != NULL");
|
|
|
-
|
|
|
- const PixelShaderId& id = m_pixel_shaders_id_table.create();
|
|
|
-
|
|
|
- PixelShader& gl_shader = m_pixel_shaders[id.index];
|
|
|
-
|
|
|
- gl_shader.gl_object = GL_CHECK(glCreateShader(GL_FRAGMENT_SHADER));
|
|
|
-
|
|
|
- GL_CHECK(glShaderSource(gl_shader.gl_object, 1, &program, NULL));
|
|
|
+public:
|
|
|
|
|
|
- GL_CHECK(glCompileShader(gl_shader.gl_object));
|
|
|
-
|
|
|
- GLint success;
|
|
|
- GL_CHECK(glGetShaderiv(gl_shader.gl_object, GL_COMPILE_STATUS, &success));
|
|
|
-
|
|
|
- if (!success)
|
|
|
+ //-----------------------------------------------------------------------------
|
|
|
+ RendererImplementation()
|
|
|
+ : m_max_texture_size(0), m_max_texture_units(0), m_max_vertex_indices(0), m_max_vertex_vertices(0),
|
|
|
+ m_max_anisotropy(0.0f), m_num_uniforms(0)
|
|
|
{
|
|
|
- GLchar info_log[256];
|
|
|
-
|
|
|
- GL_CHECK(glGetShaderInfoLog(gl_shader.gl_object, 256, NULL, info_log));
|
|
|
-
|
|
|
- Log::e("Pixel shader compilation failed.");
|
|
|
- Log::e("Log: %s", info_log);
|
|
|
- CE_ASSERT(0, "");
|
|
|
+ m_min_max_point_size[0] = 0.0f;
|
|
|
+ m_min_max_point_size[1] = 0.0f;
|
|
|
+ m_min_max_line_width[0] = 0.0f;
|
|
|
+ m_min_max_line_width[1] = 0.0f;
|
|
|
}
|
|
|
|
|
|
- return id;
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::destroy_pixel_shader(PixelShaderId id)
|
|
|
-{
|
|
|
- CE_ASSERT(m_pixel_shaders_id_table.has(id), "Pixel shader does not exist");
|
|
|
-
|
|
|
- PixelShader& gl_shader = m_pixel_shaders[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glDeleteShader(gl_shader.gl_object));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-GPUProgramId GLRenderer::create_gpu_program(VertexShaderId vs, PixelShaderId ps)
|
|
|
-{
|
|
|
- CE_ASSERT(m_vertex_shaders_id_table.has(vs), "Vertex shader does not exist");
|
|
|
- CE_ASSERT(m_pixel_shaders_id_table.has(ps), "Pixel shader does not exist");
|
|
|
-
|
|
|
- const GPUProgramId id = m_gpu_programs_id_table.create();
|
|
|
-
|
|
|
- GPUProgram& gl_program = m_gpu_programs[id.index];
|
|
|
-
|
|
|
- gl_program.gl_object = GL_CHECK(glCreateProgram());
|
|
|
-
|
|
|
- GL_CHECK(glAttachShader(gl_program.gl_object, m_vertex_shaders[id.index].gl_object));
|
|
|
- GL_CHECK(glAttachShader(gl_program.gl_object, m_pixel_shaders[id.index].gl_object));
|
|
|
-
|
|
|
- GL_CHECK(glBindAttribLocation(gl_program.gl_object, SA_VERTEX, "vertex"));
|
|
|
- GL_CHECK(glBindAttribLocation(gl_program.gl_object, SA_COORDS, "coords"));
|
|
|
- GL_CHECK(glBindAttribLocation(gl_program.gl_object, SA_NORMAL, "normal"));
|
|
|
-
|
|
|
- GL_CHECK(glLinkProgram(gl_program.gl_object));
|
|
|
-
|
|
|
- GLint success;
|
|
|
- GL_CHECK(glGetProgramiv(gl_program.gl_object, GL_LINK_STATUS, &success));
|
|
|
-
|
|
|
- if (!success)
|
|
|
+ //-----------------------------------------------------------------------------
|
|
|
+ ~RendererImplementation()
|
|
|
{
|
|
|
- GLchar info_log[256];
|
|
|
- GL_CHECK(glGetProgramInfoLog(gl_program.gl_object, 256, NULL, info_log));
|
|
|
- Log::e("GPU program compilation failed.\n");
|
|
|
- Log::e("Log: %s", info_log);
|
|
|
}
|
|
|
|
|
|
- return id;
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::destroy_gpu_program(GPUProgramId id)
|
|
|
-{
|
|
|
- CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
|
|
|
-
|
|
|
- GPUProgram& gl_program = m_gpu_programs[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glDeleteProgram(gl_program.gl_object));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_gpu_program_bool_uniform(GPUProgramId id, const char* name, bool value)
|
|
|
-{
|
|
|
- CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
|
|
|
-
|
|
|
- const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
|
|
|
-
|
|
|
- GL_CHECK(glUniform1i(uniform, (GLint) value));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_gpu_program_int_uniform(GPUProgramId id, const char* name, int value)
|
|
|
-{
|
|
|
- CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
|
|
|
-
|
|
|
- const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
|
|
|
-
|
|
|
- GL_CHECK(glUniform1i(uniform, (GLint) value));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_gpu_program_vec2_uniform(GPUProgramId id, const char* name, const Vec2& value)
|
|
|
-{
|
|
|
- CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
|
|
|
-
|
|
|
- const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
|
|
|
-
|
|
|
- GL_CHECK(glUniform2fv(uniform, 1, value.to_float_ptr()));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_gpu_program_vec3_uniform(GPUProgramId id, const char* name, const Vec3& value)
|
|
|
-{
|
|
|
- CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
|
|
|
-
|
|
|
- const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
|
|
|
-
|
|
|
- GL_CHECK(glUniform3fv(uniform, 1, value.to_float_ptr()));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_gpu_program_vec4_uniform(GPUProgramId id, const char* name, const Vec4& value)
|
|
|
-{
|
|
|
- CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
|
|
|
-
|
|
|
- const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
|
|
|
-
|
|
|
- GL_CHECK(glUniform4fv(uniform, 1, value.to_float_ptr()));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_gpu_porgram_mat3_uniform(GPUProgramId id, const char* name, const Mat3& value)
|
|
|
-{
|
|
|
- CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
|
|
|
-
|
|
|
- const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
|
|
|
-
|
|
|
- GL_CHECK(glUniformMatrix3fv(uniform, 1, GL_FALSE, value.to_float_ptr()));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_gpu_program_mat4_uniform(GPUProgramId id, const char* name, const Mat4& value)
|
|
|
-{
|
|
|
- CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
|
|
|
-
|
|
|
- const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
|
|
|
-
|
|
|
- GL_CHECK(glUniformMatrix4fv(uniform, 1, GL_FALSE, value.to_float_ptr()));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_gpu_program_sampler_uniform(GPUProgramId id, const char* name, uint32_t value)
|
|
|
-{
|
|
|
- CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
|
|
|
-
|
|
|
- const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
|
|
|
-
|
|
|
- GL_CHECK(glUniform1i(uniform, (GLint) value));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::bind_gpu_program(GPUProgramId id) const
|
|
|
-{
|
|
|
- CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
|
|
|
-
|
|
|
- const GPUProgram& gl_program = m_gpu_programs[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glUseProgram(gl_program.gl_object));
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-// RenderBufferId GLRenderer::create_render_buffer(uint32_t width, uint32_t height, PixelFormat format)
|
|
|
-// {
|
|
|
-// const RenderBufferId id = m_render_buffers_id_table.create();
|
|
|
-
|
|
|
-// GLRenderBuffer& buffer = m_render_buffers[id.index];
|
|
|
-
|
|
|
-// if (GLEW_EXT_framebuffer_object)
|
|
|
-// {
|
|
|
-// GL_CHECK(glGenFramebuffersEXT(1, &buffer.GL_CHECK(gl_frame_buffer));
|
|
|
-// GL_CHECK(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, buffer.GL_CHECK(gl_frame_buffer));
|
|
|
-
|
|
|
-// GL_CHECK(glGenRenderbuffersEXT(1, &buffer.GL_CHECK(gl_render_buffer));
|
|
|
-// GL_CHECK(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, buffer.GL_CHECK(gl_render_buffer));
|
|
|
-
|
|
|
-// GL_CHECK(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, width, height));
|
|
|
-
|
|
|
-// GL_CHECK(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, buffer.GL_CHECK(gl_render_buffer));
|
|
|
-
|
|
|
-// GL_CHECK(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
|
|
-// }
|
|
|
-
|
|
|
-// return id;
|
|
|
-// }
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-// void GLRenderer::destroy_render_buffer(RenderBufferId id)
|
|
|
-// {
|
|
|
-// GLRenderBuffer& buffer = m_render_buffers[id.index];
|
|
|
-
|
|
|
-// if (GLEW_EXT_framebuffer_object)
|
|
|
-// {
|
|
|
-// GL_CHECK(glDeleteFramebuffersEXT(1, &buffer.GL_CHECK(gl_frame_buffer));
|
|
|
-// GL_CHECK(glDeleteRenderbuffersEXT(1, &buffer.GL_CHECK(gl_render_buffer));
|
|
|
-// }
|
|
|
-
|
|
|
-// m_render_buffers_id_table.destroy(id);
|
|
|
-// }
|
|
|
+ //-----------------------------------------------------------------------------
|
|
|
+ void init()
|
|
|
+ {
|
|
|
+ m_gl_context.create_context();
|
|
|
+
|
|
|
+ #if defined(LINUX) || defined(WINDOW)
|
|
|
+ GLenum err = glewInit();
|
|
|
+ CE_ASSERT(err == GLEW_OK, "Failed to initialize GLEW");
|
|
|
+ #endif
|
|
|
+
|
|
|
+ GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_max_texture_size));
|
|
|
+ GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &m_max_texture_units));
|
|
|
+ // GL_CHECK(glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &m_max_vertex_indices));
|
|
|
+ // GL_CHECK(glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &m_max_vertex_vertices));
|
|
|
+
|
|
|
+ GL_CHECK(glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, &m_min_max_point_size[0]));
|
|
|
+ // GL_CHECK(glGetFloatv(GL_LINE_WIDTH_RANGE, &m_min_max_line_width[0]));
|
|
|
+
|
|
|
+ Log::i("OpenGL Vendor : %s", glGetString(GL_VENDOR));
|
|
|
+ Log::i("OpenGL Renderer : %s", glGetString(GL_RENDERER));
|
|
|
+ Log::i("OpenGL Version : %s", glGetString(GL_VERSION));
|
|
|
+ Log::i("GLSL Version : %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
|
|
|
+
|
|
|
+ Log::d("Min Point Size : %f", m_min_max_point_size[0]);
|
|
|
+ Log::d("Max Point Size : %f", m_min_max_point_size[1]);
|
|
|
+ Log::d("Min Line Width : %f", m_min_max_line_width[0]);
|
|
|
+ Log::d("Max Line Width : %f", m_min_max_line_width[1]);
|
|
|
+ Log::d("Max Texture Size : %dx%d", m_max_texture_size, m_max_texture_size);
|
|
|
+ Log::d("Max Texture Units : %d", m_max_texture_units);
|
|
|
+ Log::d("Max Vertex Indices : %d", m_max_vertex_indices);
|
|
|
+ Log::d("Max Vertex Vertices : %d", m_max_vertex_vertices);
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_clear_color(const Color4& color)
|
|
|
-{
|
|
|
- GL_CHECK(glClearColor(color.r, color.g, color.b, color.a));
|
|
|
-}
|
|
|
+ GL_CHECK(glDisable(GL_BLEND));
|
|
|
+ GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
|
|
+ GL_CHECK(glBlendEquation(GL_FUNC_ADD));
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_ambient_light(const Color4& color)
|
|
|
-{
|
|
|
- m_ambient_light_color = color;
|
|
|
-}
|
|
|
+ #if defined(LINUX) || defined(WINDOWS)
|
|
|
+ // Point sprites enabled by default
|
|
|
+ GL_CHECK(glEnable(GL_POINT_SPRITE));
|
|
|
+ GL_CHECK(glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE));
|
|
|
+ #endif
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::bind_texture(uint32_t unit, TextureId texture)
|
|
|
-{
|
|
|
- CE_ASSERT(m_textures_id_table.has(texture), "Texture does not exist");
|
|
|
+ Log::i("OpenGL Renderer initialized.");
|
|
|
+ }
|
|
|
|
|
|
- if (!activate_texture_unit(unit))
|
|
|
+ //-----------------------------------------------------------------------------
|
|
|
+ void shutdown()
|
|
|
{
|
|
|
- return;
|
|
|
+ m_gl_context.destroy_context();
|
|
|
}
|
|
|
|
|
|
- m_texture_unit_target[unit] = GL_TEXTURE_2D;
|
|
|
- m_texture_unit[unit] = m_textures[texture.index].gl_object;
|
|
|
-
|
|
|
- GL_CHECK(glEnable(m_texture_unit_target[unit]));
|
|
|
- GL_CHECK(glBindTexture(m_texture_unit_target[unit], m_texture_unit[unit]));
|
|
|
-}
|
|
|
+ //-----------------------------------------------------------------------------
|
|
|
+ void render(RenderContext& context)
|
|
|
+ {
|
|
|
+ //RenderTargetId old_rt;
|
|
|
+ //old_rt.id = INVALID_ID;
|
|
|
+ uint8_t layer = 0xFF;
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_texturing(uint32_t unit, bool texturing)
|
|
|
-{
|
|
|
- if (!activate_texture_unit(unit))
|
|
|
- return;
|
|
|
+ for (uint32_t s = 0; s < context.m_num_states; s++)
|
|
|
+ {
|
|
|
+ const uint64_t key_s = context.m_keys[s];
|
|
|
+ RenderKey key;
|
|
|
+ key.decode(key_s);
|
|
|
+ const RenderState& cur_state = context.m_states[s];
|
|
|
+ const uint64_t flags = cur_state.m_flags;
|
|
|
+ //const RenderTargetId& cur_rt = context.m_targets[layer];
|
|
|
+
|
|
|
+ // Check if layer changed
|
|
|
+ if (key.m_layer != layer)
|
|
|
+ {
|
|
|
+ layer = key.m_layer;
|
|
|
+
|
|
|
+ // Viewport
|
|
|
+ const ViewRect& viewport = context.m_viewports[layer];
|
|
|
+ GL_CHECK(glViewport(viewport.m_x, viewport.m_y, viewport.m_width, viewport.m_height));
|
|
|
+
|
|
|
+ // Clear frame/depth buffer
|
|
|
+ const ClearState& clear = context.m_clears[layer];
|
|
|
+ if (clear.m_flags & (CLEAR_COLOR | CLEAR_DEPTH))
|
|
|
+ {
|
|
|
+ GLbitfield gl_clear = (clear.m_flags & CLEAR_COLOR) ? GL_COLOR_BUFFER_BIT : 0;
|
|
|
+ gl_clear |= (clear.m_flags & CLEAR_DEPTH) ? GL_DEPTH_BUFFER_BIT : 0;
|
|
|
+ GL_CHECK(glClearColor(clear.m_color.r, clear.m_color.g, clear.m_color.b, clear.m_color.a));
|
|
|
+ #if defined(LINUX) || defined(WINDOWS)
|
|
|
+ GL_CHECK(glClearDepth(clear.m_depth));
|
|
|
+ #elif defined(ANDROID)
|
|
|
+ GL_CHECK(glClearDepthf(clear.m_depth));
|
|
|
+ #endif
|
|
|
+ GL_CHECK(glClear(gl_clear));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Scissor
|
|
|
+ const ViewRect& scissor = context.m_scissors[layer];
|
|
|
+ if (scissor.area() != 0)
|
|
|
+ {
|
|
|
+ GL_CHECK(glEnable(GL_SCISSOR_TEST));
|
|
|
+ GL_CHECK(glScissor(scissor.m_x, scissor.m_y, scissor.m_width, scissor.m_height));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ GL_CHECK(glDisable(GL_SCISSOR_TEST));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Depth write
|
|
|
+ if (flags & (STATE_DEPTH_WRITE))
|
|
|
+ {
|
|
|
+ GL_CHECK(glDepthMask(flags & STATE_DEPTH_WRITE));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Color/Alpha write
|
|
|
+ if (flags & (STATE_COLOR_WRITE | STATE_ALPHA_WRITE))
|
|
|
+ {
|
|
|
+ GLboolean cw = !!(flags & STATE_COLOR_WRITE);
|
|
|
+ GLboolean aw = !!(flags & STATE_ALPHA_WRITE);
|
|
|
+ GL_CHECK(glColorMask(cw, cw, cw, aw));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Face culling
|
|
|
+ if (flags & (STATE_CULL_CW | STATE_CULL_CCW))
|
|
|
+ {
|
|
|
+ if (flags & STATE_CULL_CW)
|
|
|
+ {
|
|
|
+ GL_CHECK(glEnable(GL_CULL_FACE));
|
|
|
+ GL_CHECK(glCullFace(GL_BACK));
|
|
|
+ }
|
|
|
+ else if (flags & STATE_CULL_CCW)
|
|
|
+ {
|
|
|
+ GL_CHECK(glEnable(GL_CULL_FACE));
|
|
|
+ GL_CHECK(glCullFace(GL_FRONT));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ GL_CHECK(glDisable(GL_CULL_FACE));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Bind GPU program
|
|
|
+ if (cur_state.program.id != INVALID_ID)
|
|
|
+ {
|
|
|
+ const GPUProgram& gpu_program = m_gpu_programs[cur_state.program.index];
|
|
|
+ GL_CHECK(glUseProgram(gpu_program.m_id));
|
|
|
+ // Not necessarily here...
|
|
|
+ gpu_program.commit();
|
|
|
+
|
|
|
+ for (uint8_t uniform = 0; uniform < gpu_program.m_num_stock_uniforms; uniform++)
|
|
|
+ {
|
|
|
+ const GLint& uniform_location = gpu_program.m_stock_uniform_locations[uniform];
|
|
|
+ const Mat4& view = context.m_view_matrices[layer];
|
|
|
+ const Mat4& projection = context.m_projection_matrices[layer];
|
|
|
+
|
|
|
+ switch (gpu_program.m_stock_uniforms[uniform])
|
|
|
+ {
|
|
|
+ case UNIFORM_VIEW:
|
|
|
+ {
|
|
|
+ GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, view.to_float_ptr()));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case UNIFORM_MODEL:
|
|
|
+ {
|
|
|
+ GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, cur_state.pose.to_float_ptr()));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case UNIFORM_MODEL_VIEW:
|
|
|
+ {
|
|
|
+ GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, (view *
|
|
|
+ cur_state.pose).to_float_ptr()));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case UNIFORM_MODEL_VIEW_PROJECTION:
|
|
|
+ {
|
|
|
+ GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, (projection * view *
|
|
|
+ cur_state.pose).to_float_ptr()));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case UNIFORM_TIME_SINCE_START:
|
|
|
+ {
|
|
|
+ GL_CHECK(glUniform1f(uniform_location, device()->time_since_start()));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ {
|
|
|
+ CE_ASSERT(false, "Oops, wrong stock uniform!");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ GL_CHECK(glUseProgram(0));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Bind array buffers
|
|
|
+ const VertexBufferId& vb = cur_state.vb;
|
|
|
+ if (vb.id != INVALID_ID)
|
|
|
+ {
|
|
|
+ const VertexBuffer& vertex_buffer = m_vertex_buffers[vb.index];
|
|
|
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer.m_id);
|
|
|
+
|
|
|
+ const GPUProgram& gpu_program = m_gpu_programs[cur_state.program.index];
|
|
|
+ gpu_program.bind_attributes(vertex_buffer.m_format);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
|
|
|
+ }
|
|
|
+
|
|
|
+ const IndexBufferId& ib = cur_state.ib;
|
|
|
+ if (ib.id != INVALID_ID)
|
|
|
+ {
|
|
|
+ const IndexBuffer& index_buffer = m_index_buffers[ib.index];
|
|
|
+ uint32_t prim_type = (flags & STATE_PRIMITIVE_MASK) >> STATE_PRIMITIVE_SHIFT;
|
|
|
+ GLenum gl_prim_type = PRIMITIVE_TYPE_TABLE[prim_type];
|
|
|
+ GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.m_id));
|
|
|
+ GL_CHECK(glDrawElements(gl_prim_type, index_buffer.m_index_count, GL_UNSIGNED_SHORT, 0));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Bind textures
|
|
|
+ {
|
|
|
+ uint64_t flags = STATE_TEXTURE_0;
|
|
|
+ for (uint32_t unit = 0; unit < STATE_MAX_TEXTURES; unit++)
|
|
|
+ {
|
|
|
+ const Sampler& sampler = cur_state.samplers[unit];
|
|
|
+
|
|
|
+ if (sampler.sampler_id.id != INVALID_ID)
|
|
|
+ {
|
|
|
+ switch (sampler.flags & SAMPLER_MASK)
|
|
|
+ {
|
|
|
+ case SAMPLER_TEXTURE:
|
|
|
+ {
|
|
|
+ Texture& texture = m_textures[sampler.sampler_id.index];
|
|
|
+ texture.commit(unit, sampler.flags);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ {
|
|
|
+ CE_ASSERT(false, "Oops, sampler unknown");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ flags <<= 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (texturing)
|
|
|
- {
|
|
|
- GL_CHECK(glEnable(m_texture_unit_target[unit]));
|
|
|
+ GL_CHECK(glFinish());
|
|
|
+ m_gl_context.swap_buffers();
|
|
|
}
|
|
|
- else
|
|
|
- {
|
|
|
- GL_CHECK(glDisable(m_texture_unit_target[unit]));
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_texture_wrap(uint32_t unit, TextureWrap wrap)
|
|
|
-{
|
|
|
- GLenum gl_wrap = GL::texture_wrap(wrap);
|
|
|
+private:
|
|
|
|
|
|
- GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_WRAP_S, gl_wrap));
|
|
|
- GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_WRAP_T, gl_wrap));
|
|
|
-}
|
|
|
+ GLContext m_gl_context;
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_texture_filter(uint32_t unit, TextureFilter filter)
|
|
|
-{
|
|
|
- if (!activate_texture_unit(unit))
|
|
|
- return;
|
|
|
+ // Limits
|
|
|
+ int32_t m_max_texture_size;
|
|
|
+ int32_t m_max_texture_units;
|
|
|
+ int32_t m_max_vertex_indices;
|
|
|
+ int32_t m_max_vertex_vertices;
|
|
|
|
|
|
- GLint min_filter;
|
|
|
- GLint mag_filter;
|
|
|
+ float m_max_anisotropy;
|
|
|
+ float m_min_max_point_size[2];
|
|
|
+ float m_min_max_line_width[2];
|
|
|
|
|
|
- GL::texture_filter(filter, min_filter, mag_filter);
|
|
|
+ VertexBuffer m_vertex_buffers[CROWN_MAX_VERTEX_BUFFERS];
|
|
|
+ IndexBuffer m_index_buffers[CROWN_MAX_INDEX_BUFFERS];
|
|
|
+ Texture m_textures[CROWN_MAX_TEXTURES];
|
|
|
+ Shader m_shaders[CROWN_MAX_SHADERS];
|
|
|
+ GPUProgram m_gpu_programs[CROWN_MAX_GPU_PROGRAMS];
|
|
|
+ uint32_t m_num_uniforms;
|
|
|
+ Uniform m_uniforms[CROWN_MAX_UNIFORMS];
|
|
|
+ RenderTarget m_render_targets[CROWN_MAX_RENDER_TARGETS];
|
|
|
|
|
|
- GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_MIN_FILTER, min_filter));
|
|
|
- GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_MAG_FILTER, mag_filter));
|
|
|
-}
|
|
|
+private:
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_backface_culling(bool culling)
|
|
|
-{
|
|
|
- if (culling)
|
|
|
- {
|
|
|
- GL_CHECK(glEnable(GL_CULL_FACE));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- GL_CHECK(glDisable(GL_CULL_FACE));
|
|
|
- }
|
|
|
-}
|
|
|
+ friend class Renderer;
|
|
|
+};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_depth_test(bool test)
|
|
|
+Renderer::Renderer(Allocator& a)
|
|
|
+ : m_allocator(a), m_impl(NULL), m_thread("render-thread"), m_submit(&m_contexts[0]), m_draw(&m_contexts[1]),
|
|
|
+ m_is_initialized(false), m_should_run(false)
|
|
|
{
|
|
|
- if (test)
|
|
|
- {
|
|
|
- GL_CHECK(glEnable(GL_DEPTH_TEST));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- GL_CHECK(glDisable(GL_DEPTH_TEST));
|
|
|
- }
|
|
|
+ m_impl = CE_NEW(a, RendererImplementation);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_depth_write(bool write)
|
|
|
+Renderer::~Renderer()
|
|
|
{
|
|
|
- GL_CHECK(glDepthMask((GLboolean) write));
|
|
|
+ CE_DELETE(m_allocator, m_impl);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_depth_func(CompareFunction func)
|
|
|
+void Renderer::init_impl()
|
|
|
{
|
|
|
- GLenum gl_func = GL::compare_function(func);
|
|
|
-
|
|
|
- GL_CHECK(glDepthFunc(gl_func));
|
|
|
+ m_impl->init();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_blending(bool blending)
|
|
|
+void Renderer::shutdown_impl()
|
|
|
{
|
|
|
- if (blending)
|
|
|
- {
|
|
|
- GL_CHECK(glEnable(GL_BLEND));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- GL_CHECK(glDisable(GL_BLEND));
|
|
|
- }
|
|
|
+ m_impl->shutdown();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_blending_params(BlendEquation equation, BlendFunction src, BlendFunction dst, const Color4& color)
|
|
|
+void Renderer::render_impl()
|
|
|
{
|
|
|
- GLenum gl_equation = GL::blend_equation(equation);
|
|
|
-
|
|
|
- GL_CHECK(glBlendEquation(gl_equation));
|
|
|
-
|
|
|
- GLenum gl_src_factor = GL::blend_function(src);
|
|
|
- GLenum gl_dst_factor = GL::blend_function(dst);
|
|
|
+ m_impl->render(*m_draw);
|
|
|
|
|
|
- GL_CHECK(glBlendFunc(gl_src_factor, gl_dst_factor));
|
|
|
-
|
|
|
- GL_CHECK(glBlendColor(color.r, color.g, color.b, color.a));
|
|
|
+ m_draw->clear();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_color_write(bool write)
|
|
|
+void Renderer::create_vertex_buffer_impl(VertexBufferId id, size_t count, VertexFormat format, const void* vertices)
|
|
|
{
|
|
|
- if (write)
|
|
|
- {
|
|
|
- GL_CHECK(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- GL_CHECK(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
|
|
|
- }
|
|
|
+ m_impl->m_vertex_buffers[id.index].create(count, format, vertices);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_front_face(FrontFace face)
|
|
|
+void Renderer::create_dynamic_vertex_buffer_impl(VertexBufferId id, size_t count, VertexFormat format)
|
|
|
{
|
|
|
- const GLenum gl_face = (face == FF_CCW) ? GL_CCW : GL_CW;
|
|
|
-
|
|
|
- GL_CHECK(glFrontFace(gl_face));
|
|
|
+ m_impl->m_vertex_buffers[id.index].create(count, format, NULL);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_viewport_params(int32_t x, int32_t y, int32_t width, int32_t height)
|
|
|
+void Renderer::update_vertex_buffer_impl(VertexBufferId id, size_t offset, size_t count, const void* vertices)
|
|
|
{
|
|
|
- m_viewport[0] = x;
|
|
|
- m_viewport[1] = y;
|
|
|
- m_viewport[2] = width;
|
|
|
- m_viewport[3] = height;
|
|
|
-
|
|
|
- GL_CHECK(glViewport(x, y, width, height));
|
|
|
+ m_impl->m_vertex_buffers[id.index].update(offset, count, vertices);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::get_viewport_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height)
|
|
|
+void Renderer::destroy_vertex_buffer_impl(VertexBufferId id)
|
|
|
{
|
|
|
- x = m_viewport[0];
|
|
|
- y = m_viewport[1];
|
|
|
- width = m_viewport[2];
|
|
|
- height = m_viewport[3];
|
|
|
+ m_impl->m_vertex_buffers[id.index].destroy();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_scissor(bool scissor)
|
|
|
+void Renderer::create_index_buffer_impl(IndexBufferId id, size_t count, const void* indices)
|
|
|
{
|
|
|
- if (scissor)
|
|
|
- {
|
|
|
- GL_CHECK(glEnable(GL_SCISSOR_TEST));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- GL_CHECK(glDisable(GL_SCISSOR_TEST));
|
|
|
- }
|
|
|
+ m_impl->m_index_buffers[id.index].create(count, indices);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_scissor_params(int32_t x, int32_t y, int32_t width, int32_t height)
|
|
|
+void Renderer::create_dynamic_index_buffer_impl(IndexBufferId id, size_t count)
|
|
|
{
|
|
|
- m_scissor[0] = x;
|
|
|
- m_scissor[1] = y;
|
|
|
- m_scissor[2] = width;
|
|
|
- m_scissor[3] = height;
|
|
|
-
|
|
|
- GL_CHECK(glScissor(x, y, width, height));
|
|
|
+ m_impl->m_index_buffers[id.index].create(count, NULL);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::get_scissor_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height)
|
|
|
+void Renderer::update_index_buffer_impl(IndexBufferId id, size_t offset, size_t count, const void* indices)
|
|
|
{
|
|
|
- x = m_scissor[0];
|
|
|
- y = m_scissor[1];
|
|
|
- width = m_scissor[2];
|
|
|
- height = m_scissor[3];
|
|
|
+ m_impl->m_index_buffers[id.index].update(offset, count, indices);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::frame()
|
|
|
+void Renderer::destroy_index_buffer_impl(IndexBufferId id)
|
|
|
{
|
|
|
- // Clear frame/depth buffer
|
|
|
- GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
|
|
|
-
|
|
|
- // Bind the default gpu program
|
|
|
- bind_gpu_program(m_default_gpu_program);
|
|
|
-
|
|
|
- set_gpu_program_mat4_uniform(m_default_gpu_program, "mvp_matrix", m_model_view_projection_matrix);
|
|
|
- set_gpu_program_vec3_uniform(m_default_gpu_program, "color", Vec3(0, 1, 0));
|
|
|
-
|
|
|
- GL_CHECK(glFinish());
|
|
|
-
|
|
|
- m_context.swap_buffers();
|
|
|
+ m_impl->m_index_buffers[id.index].destroy();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-Mat4 GLRenderer::get_matrix(MatrixType type) const
|
|
|
+void Renderer::create_texture_impl(TextureId id, uint32_t width, uint32_t height, PixelFormat format, const void* data)
|
|
|
{
|
|
|
- return m_matrix[type];
|
|
|
+ m_impl->m_textures[id.index].create(width, height, format, data);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::set_matrix(MatrixType type, const Mat4& matrix)
|
|
|
+void Renderer::update_texture_impl(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data)
|
|
|
{
|
|
|
- m_matrix[type] = matrix;
|
|
|
-
|
|
|
- switch (type)
|
|
|
- {
|
|
|
- case MT_VIEW:
|
|
|
- case MT_MODEL:
|
|
|
- {
|
|
|
- m_model_view_matrix = m_matrix[MT_VIEW] * m_matrix[MT_MODEL];
|
|
|
- break;
|
|
|
- }
|
|
|
- case MT_PROJECTION:
|
|
|
- {
|
|
|
- m_model_view_projection_matrix = m_matrix[MT_PROJECTION] * m_model_view_matrix;
|
|
|
- break;
|
|
|
- }
|
|
|
- default:
|
|
|
- {
|
|
|
- break;
|
|
|
- CE_ASSERT(0, "");
|
|
|
- }
|
|
|
- }
|
|
|
+ m_impl->m_textures[id.index].update(x, y, width, height, data);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::bind_vertex_buffer(VertexBufferId vb) const
|
|
|
+void Renderer::destroy_texture_impl(TextureId id)
|
|
|
{
|
|
|
- CE_ASSERT(m_vertex_buffers_id_table.has(vb), "Vertex buffer does not exist");
|
|
|
-
|
|
|
- const VertexBuffer& vertex_buffer = m_vertex_buffers[vb.index];
|
|
|
-
|
|
|
- GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer.gl_object));
|
|
|
-
|
|
|
- switch (vertex_buffer.format)
|
|
|
- {
|
|
|
- case VF_XY_FLOAT_32:
|
|
|
- {
|
|
|
- GL_CHECK(glEnableVertexAttribArray(SA_VERTEX));
|
|
|
- GL_CHECK(glVertexAttribPointer(SA_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, 0));
|
|
|
- break;
|
|
|
- }
|
|
|
- case VF_XYZ_FLOAT_32:
|
|
|
- {
|
|
|
- GL_CHECK(glEnableVertexAttribArray(SA_VERTEX));
|
|
|
- GL_CHECK(glVertexAttribPointer(SA_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0));
|
|
|
- break;
|
|
|
- }
|
|
|
- case VF_UV_FLOAT_32:
|
|
|
- {
|
|
|
- GL_CHECK(glEnableVertexAttribArray(SA_COORDS));
|
|
|
- GL_CHECK(glVertexAttribPointer(SA_COORDS, 2, GL_FLOAT, GL_FALSE, 0, 0));
|
|
|
- break;
|
|
|
- }
|
|
|
- case VF_UVT_FLOAT_32:
|
|
|
- {
|
|
|
- GL_CHECK(glEnableVertexAttribArray(SA_COORDS));
|
|
|
- GL_CHECK(glVertexAttribPointer(SA_COORDS, 3, GL_FLOAT, GL_FALSE, 0, 0));
|
|
|
- break;
|
|
|
- }
|
|
|
- case VF_XYZ_NORMAL_FLOAT_32:
|
|
|
- {
|
|
|
- GL_CHECK(glEnableVertexAttribArray(SA_NORMAL));
|
|
|
- GL_CHECK(glVertexAttribPointer(SA_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, 0));
|
|
|
- break;
|
|
|
- }
|
|
|
- case VF_XYZ_UV_XYZ_NORMAL_FLOAT_32:
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
- default:
|
|
|
- {
|
|
|
- CE_ASSERT(0, "Vertex format unknown");
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
+ m_impl->m_textures[id.index].destroy();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::draw_triangles(IndexBufferId id) const
|
|
|
+void Renderer::create_shader_impl(ShaderId id, ShaderType type, const char* text)
|
|
|
{
|
|
|
- CE_ASSERT(m_index_buffers_id_table.has(id), "Index buffer does not exist");
|
|
|
-
|
|
|
- const IndexBuffer& index_buffer = m_index_buffers[id.index];
|
|
|
-
|
|
|
- GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.gl_object));
|
|
|
-
|
|
|
- GL_CHECK(glDrawElements(GL_TRIANGLES, index_buffer.index_count, GL_UNSIGNED_SHORT, 0));
|
|
|
+ m_impl->m_shaders[id.index].create(type, text);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-// void GLRenderer::bind_render_buffer(RenderBufferId id) const
|
|
|
-// {
|
|
|
-// CE_ASSERT(m_render_buffers_id_table.has(id), "Render buffer does not exist");
|
|
|
-
|
|
|
-// const GLRenderBuffer& render_buffer = m_render_buffers[id.index];
|
|
|
-// }
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::draw_lines(const float* vertices, const float* colors, uint32_t count)
|
|
|
+void Renderer::destroy_shader_impl(ShaderId id)
|
|
|
{
|
|
|
- GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
|
|
|
- GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
|
|
-
|
|
|
- GL_CHECK(glEnableClientState(GL_VERTEX_ARRAY));
|
|
|
- GL_CHECK(glEnableClientState(GL_COLOR_ARRAY));
|
|
|
-
|
|
|
- GL_CHECK(glVertexPointer(3, GL_FLOAT, 0, vertices));
|
|
|
- GL_CHECK(glColorPointer(4, GL_FLOAT, 0, colors));
|
|
|
-
|
|
|
- GL_CHECK(glDrawArrays(GL_LINES, 0, count));
|
|
|
-
|
|
|
- GL_CHECK(glDisableClientState(GL_COLOR_ARRAY));
|
|
|
- GL_CHECK(glDisableClientState(GL_VERTEX_ARRAY));
|
|
|
+ m_impl->m_shaders[id.index].destroy();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::load_default_shaders()
|
|
|
+void Renderer::create_gpu_program_impl(GPUProgramId id, ShaderId vertex, ShaderId pixel)
|
|
|
{
|
|
|
- static const char* vs_text =
|
|
|
- "in vec4 vertex;"
|
|
|
- "in vec2 coords;"
|
|
|
- "uniform mat4 mvp_matrix;"
|
|
|
- "uniform vec3 color;"
|
|
|
-
|
|
|
- "void main(void)"
|
|
|
- "{"
|
|
|
- " gl_Position = mvp_matrix * vertex;"
|
|
|
-
|
|
|
- " gl_FrontColor = vec4(color, 1.0);"
|
|
|
- "}";
|
|
|
-
|
|
|
- static const char* ps_text =
|
|
|
- "void main(void)"
|
|
|
- "{"
|
|
|
- " gl_FragColor = gl_Color;"
|
|
|
- "}";
|
|
|
-
|
|
|
- m_default_vertex_shader = create_vertex_shader(vs_text);
|
|
|
- m_default_pixel_shader = create_pixel_shader(ps_text);
|
|
|
-
|
|
|
- // Create and bind the default program
|
|
|
- m_default_gpu_program = create_gpu_program(m_default_vertex_shader, m_default_pixel_shader);
|
|
|
+ Shader& vs = m_impl->m_shaders[vertex.index];
|
|
|
+ Shader& ps = m_impl->m_shaders[pixel.index];
|
|
|
+ m_impl->m_gpu_programs[id.index].create(vs, ps, m_impl->m_num_uniforms, m_impl->m_uniforms);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::unload_default_shaders()
|
|
|
+void Renderer::destroy_gpu_program_impl(GPUProgramId id)
|
|
|
{
|
|
|
- destroy_pixel_shader(m_default_pixel_shader);
|
|
|
- destroy_vertex_shader(m_default_vertex_shader);
|
|
|
-
|
|
|
- destroy_gpu_program(m_default_gpu_program);
|
|
|
+ m_impl->m_gpu_programs[id.index].destroy();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void GLRenderer::reload_default_shaders()
|
|
|
+void Renderer::create_uniform_impl(UniformId id, const char* name, UniformType type, uint8_t num)
|
|
|
{
|
|
|
+ m_impl->m_uniforms[id.index].create(name, type, num);
|
|
|
+ m_impl->m_num_uniforms++;
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-bool GLRenderer::activate_texture_unit(uint32_t unit)
|
|
|
+void Renderer::update_uniform_impl(UniformId id, size_t size, const void* data)
|
|
|
{
|
|
|
- if (unit >= (uint32_t) m_max_texture_units)
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- GL_CHECK(glActiveTexture(GL_TEXTURE0 + unit));
|
|
|
- m_active_texture_unit = unit;
|
|
|
-
|
|
|
- return true;
|
|
|
+ m_impl->m_uniforms[id.index].update(size, data);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-GLint GLRenderer::find_gpu_program_uniform(GLuint program, const char* name) const
|
|
|
+void Renderer::destroy_uniform_impl(UniformId id)
|
|
|
{
|
|
|
- GLint uniform = GL_CHECK(glGetUniformLocation(program, name));
|
|
|
+ m_impl->m_uniforms[id.index].destroy();
|
|
|
+ m_impl->m_num_uniforms--;
|
|
|
+}
|
|
|
|
|
|
- CE_ASSERT(uniform != -1, "Uniform does not exist");
|
|
|
+// //-----------------------------------------------------------------------------
|
|
|
+// void Renderer::create_render_target_impl(RenderTargetId id, uint16_t width, uint16_t height, RenderTargetFormat format)
|
|
|
+// {
|
|
|
|
|
|
- return uniform;
|
|
|
-}
|
|
|
+// }
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-Renderer* Renderer::create(Allocator& a)
|
|
|
-{
|
|
|
- return CE_NEW(a, GLRenderer);
|
|
|
-}
|
|
|
+// //-----------------------------------------------------------------------------
|
|
|
+// void Renderer::destroy_render_target_impl(RenderTargetId id)
|
|
|
+// {
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void Renderer::destroy(Allocator& a, Renderer* renderer)
|
|
|
-{
|
|
|
- CE_DELETE(a, renderer);
|
|
|
-}
|
|
|
+// }
|
|
|
|
|
|
} // namespace crown
|
|
|
-
|