| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611 |
- /*
- Copyright (c) 2013 Daniele Bartolini, Michele Rossi
- Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- 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"
- #include "Allocator.h"
- #include "Assert.h"
- #include "Types.h"
- #include "GLRenderer.h"
- #include "Log.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
- {
- //-----------------------------------------------------------------------------
- const GLenum TEXTURE_MIN_FILTER_TABLE[] =
- {
- 0, // Unused
- GL_NEAREST,
- GL_LINEAR,
- GL_NEAREST_MIPMAP_LINEAR,
- GL_LINEAR_MIPMAP_LINEAR
- };
- //-----------------------------------------------------------------------------
- const GLenum TEXTURE_MAG_FILTER_TABLE[] =
- {
- 0, // Unused
- GL_NEAREST,
- GL_LINEAR,
- GL_LINEAR,
- GL_LINEAR
- };
- //-----------------------------------------------------------------------------
- const GLenum TEXTURE_WRAP_TABLE[] =
- {
- 0, // Unused
- GL_CLAMP,
- GL_CLAMP_TO_EDGE,
- GL_CLAMP_TO_BORDER,
- GL_REPEAT
- };
- //-----------------------------------------------------------------------------
- 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_textures_id_table(m_allocator, CROWN_MAX_TEXTURES),
- m_active_texture_unit(0),
- m_vertex_buffers_id_table(m_allocator, CROWN_MAX_VERTEX_BUFFERS),
- m_index_buffers_id_table(m_allocator, CROWN_MAX_INDEX_BUFFERS),
- m_shaders_id_table(m_allocator, CROWN_MAX_SHADERS),
- m_gpu_programs_id_table(m_allocator, CROWN_MAX_GPU_PROGRAMS),
- m_uniforms_id_table(m_allocator, CROWN_MAX_UNIFORMS),
- m_render_targets_id_table(m_allocator, CROWN_MAX_RENDER_TARGETS)
- {
- 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 texture units
- for (uint32_t i = 0; i < CROWN_MAX_TEXTURE_UNITS; i++)
- {
- m_texture_unit[i] = 0;
- m_texture_unit_target[i] = GL_TEXTURE_2D;
- }
- }
- //-----------------------------------------------------------------------------
- GLRenderer::~GLRenderer()
- {
- }
- //-----------------------------------------------------------------------------
- void GLRenderer::init()
- {
- 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));
- 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);
- 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(glShadeModel(GL_SMOOTH));
- // Enable depth test
- GL_CHECK(glEnable(GL_DEPTH_TEST));
- GL_CHECK(glDepthFunc(GL_LEQUAL));
- GL_CHECK(glClearDepth(1.0));
- // 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.");
- }
- //-----------------------------------------------------------------------------
- void GLRenderer::shutdown()
- {
- m_context.destroy_context();
- }
- //-----------------------------------------------------------------------------
- VertexBufferId GLRenderer::create_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];
- buffer.create(count, format, vertices);
- 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];
- buffer.update(offset, count, 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];
- buffer.destroy();
- 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];
- buffer.create(count, indices);
- return id;
- }
- //-----------------------------------------------------------------------------
- void GLRenderer::destroy_index_buffer(IndexBufferId id)
- {
- CE_ASSERT(m_index_buffers_id_table.has(id), "Index buffer does not exist");
- IndexBuffer& buffer = m_index_buffers[id.index];
- buffer.destroy();
- m_index_buffers_id_table.destroy(id);
- }
- //-----------------------------------------------------------------------------
- TextureId GLRenderer::create_texture(uint32_t width, uint32_t height, PixelFormat format, const void* data)
- {
- const TextureId id = m_textures_id_table.create();
- Texture& texture = m_textures[id.index];
- texture.create(width, height, format, data);
- 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& texture = m_textures[id.index];
- texture.update(x, y, width, height, data);
- }
- //-----------------------------------------------------------------------------
- void GLRenderer::destroy_texture(TextureId id)
- {
- CE_ASSERT(m_textures_id_table.has(id), "Texture does not exist");
- Texture& texture = m_textures[id.index];
- texture.destroy();
- m_textures_id_table.destroy(id);
- }
- //-----------------------------------------------------------------------------
- ShaderId GLRenderer::create_shader(ShaderType type, const char* text)
- {
- CE_ASSERT_NOT_NULL(text);
- const ShaderId& id = m_shaders_id_table.create();
- Shader& shader = m_shaders[id.index];
- shader.create(type, text);
- return id;
- }
- //-----------------------------------------------------------------------------
- void GLRenderer::destroy_shader(ShaderId id)
- {
- CE_ASSERT(m_shaders_id_table.has(id), "Shader does not exist");
- Shader& shader = m_shaders[id.index];
- shader.destroy();
- m_shaders_id_table.destroy(id);
- }
- //-----------------------------------------------------------------------------
- GPUProgramId GLRenderer::create_gpu_program(ShaderId vertex, ShaderId pixel)
- {
- CE_ASSERT(m_shaders_id_table.has(vertex), "Vertex shader does not exist");
- CE_ASSERT(m_shaders_id_table.has(pixel), "Pixel shader does not exist");
- const GPUProgramId id = m_gpu_programs_id_table.create();
- GPUProgram& program = m_gpu_programs[id.index];
- program.create(m_shaders[vertex.index], m_shaders[pixel.index]);
- return id;
- }
- //-----------------------------------------------------------------------------
- void GLRenderer::destroy_gpu_program(GPUProgramId id)
- {
- CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
- GPUProgram& program = m_gpu_programs[id.index];
- program.destroy();
- m_gpu_programs_id_table.destroy(id);
- }
- //-----------------------------------------------------------------------------
- UniformId GLRenderer::create_uniform(const char* name, UniformType type)
- {
- const UniformId id = m_uniforms_id_table.create();
- Uniform& uniform = m_uniforms[id.index];
- uniform.m_name = hash::murmur2_32(name, string::strlen(name), 0);
- uniform.m_type = type;
- return id;
- }
- //-----------------------------------------------------------------------------
- void GLRenderer::destroy_uniform(UniformId id)
- {
- CE_ASSERT(m_uniforms_id_table.has(id), "Uniform does not exist");
- m_uniforms_id_table.destroy(id);
- }
- //-----------------------------------------------------------------------------
- RenderTargetId GLRenderer::create_render_target(uint16_t width, uint16_t height, RenderTargetFormat format)
- {
- const RenderTargetId id = m_render_targets_id_table.create();
- RenderTarget& target = m_render_targets[id.index];
- target.create(width, height, format);
- return id;
- }
- //-----------------------------------------------------------------------------
- void GLRenderer::destroy_render_target(RenderTargetId id)
- {
- CE_ASSERT(m_render_targets_id_table.has(id), "Render target does not exist");
- RenderTarget& target = m_render_targets[id.index];
- target.destroy();
- m_render_targets_id_table.destroy(id);
- }
- // //-----------------------------------------------------------------------------
- // void GLRenderer::set_depth_test(bool test)
- // {
- // if (test)
- // {
- // GL_CHECK(glEnable(GL_DEPTH_TEST));
- // }
- // else
- // {
- // GL_CHECK(glDisable(GL_DEPTH_TEST));
- // }
- // }
- // //-----------------------------------------------------------------------------
- // void GLRenderer::set_depth_func(CompareFunction func)
- // {
- // GLenum gl_func = GL::compare_function(func);
- // GL_CHECK(glDepthFunc(gl_func));
- // }
- //-----------------------------------------------------------------------------
- void GLRenderer::frame()
- {
- //RenderTargetId old_rt;
- //old_rt.id = INVALID_ID;
- uint8_t layer = 0xFF;
- for (uint32_t s = 0; s < m_render_context.m_num_states; s++)
- {
- const uint64_t key_s = m_render_context.m_keys[s];
- RenderKey key;
- key.decode(key_s);
- const RenderState& cur_state = m_render_context.m_states[s];
- const uint64_t flags = cur_state.m_flags;
- //const RenderTargetId& cur_rt = m_render_context.m_targets[layer];
- // Check if layer changed
- if (key.m_layer != layer)
- {
- layer = key.m_layer;
- // Viewport
- const ViewRect& viewport = m_render_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 = m_render_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));
- GL_CHECK(glClearDepth(clear.m_depth));
- GL_CHECK(glClear(gl_clear));
- }
- }
- // Scissor
- const ViewRect& scissor = m_render_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));
- 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 = m_render_context.m_view_matrices[layer];
- const Mat4& projection = m_render_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);
- switch (vertex_buffer.m_format)
- {
- case VF_XY_FLOAT_32:
- {
- GL_CHECK(glEnableVertexAttribArray(ATTRIB_POSITION));
- GL_CHECK(glVertexAttribPointer(ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, 0));
- break;
- }
- case VF_XYZ_FLOAT_32:
- {
- GL_CHECK(glEnableVertexAttribArray(ATTRIB_POSITION));
- GL_CHECK(glVertexAttribPointer(ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, 0, 0));
- break;
- }
- case VF_XYZ_NORMAL_FLOAT_32:
- {
- GL_CHECK(glEnableVertexAttribArray(ATTRIB_NORMAL));
- GL_CHECK(glVertexAttribPointer(ATTRIB_NORMAL, 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_UV_XYZ_NORMAL_FLOAT_32:
- {
- break;
- }
- default:
- {
- CE_ASSERT(false, "Oops, vertex format unknown!");
- break;
- }
- }
- }
- 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];
- GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.m_id));
- GL_CHECK(glDrawElements(GL_TRIANGLES, index_buffer.m_index_count, GL_UNSIGNED_SHORT, 0));
- }
- else
- {
- GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
- }
- }
- GL_CHECK(glFinish());
- m_render_context.clear();
- m_context.swap_buffers();
- }
- //-----------------------------------------------------------------------------
- void GLRenderer::draw_lines(const float* vertices, const float* colors, uint32_t count)
- {
- 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));
- }
- //-----------------------------------------------------------------------------
- Renderer* Renderer::create(Allocator& a)
- {
- return CE_NEW(a, GLRenderer);
- }
- //-----------------------------------------------------------------------------
- void Renderer::destroy(Allocator& a, Renderer* renderer)
- {
- CE_DELETE(a, renderer);
- }
- } // namespace crown
|