diff --git a/shaders/lines/fs_lines.sc b/shaders/lines/fs_lines.sc new file mode 100644 index 0000000..4fc0a0a --- /dev/null +++ b/shaders/lines/fs_lines.sc @@ -0,0 +1,13 @@ +$input v_color0 + +/* + * Copyright 2011-2015 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +#include "../common/common.sh" + +void main() +{ + gl_FragColor = v_color0; +} diff --git a/shaders/lines/varying.def.sc b/shaders/lines/varying.def.sc new file mode 100644 index 0000000..3122ec0 --- /dev/null +++ b/shaders/lines/varying.def.sc @@ -0,0 +1,7 @@ +vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 1.0, 1.0); + +vec3 a_position : POSITION; +vec3 a_texcoord0 : TEXCOORD0 = vec3(1.0, 0.0, 1.0); +vec3 a_texcoord1 : TEXCOORD1 = vec3(1.0, 0.0, 1.0); +float a_texcoord2 : TEXCOORD2 = 0.0; + diff --git a/shaders/lines/vs_lines.sc b/shaders/lines/vs_lines.sc new file mode 100644 index 0000000..b915c4e --- /dev/null +++ b/shaders/lines/vs_lines.sc @@ -0,0 +1,65 @@ +$input a_position, a_texcoord0, a_texcoord1, a_texcoord2 +$output v_color0 + +/* + * Copyright 2011-2015 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +#include "../common/common.sh" + +uniform vec4 u_line_params; + +#define thickness u_line_params.x +#define miter u_line_params.y +#define width u_line_params.z +#define height u_line_params.w +#define current_pos a_position +#define prev_pos a_texcoord0 +#define next_pos a_texcoord1 +#define direction a_texcoord2 + +void main() +{ + float aspect = width / height; + vec2 aspect_vec = vec2(aspect, 1.0); + + vec4 current_proj = mul(u_modelViewProj, vec4(current_pos, 1.0)); + vec4 prev_proj = mul(u_modelViewProj, vec4(prev_pos, 1.0)); + vec4 next_proj = mul(u_modelViewProj, vec4(next_pos, 1.0)); + + vec2 current_screen = current_proj.xy / current_proj.w * aspect_vec; + vec2 prev_screen = prev_proj.xy / prev_proj.w * aspect_vec; + vec2 next_screen = next_proj.xy / next_proj.w * aspect_vec; + + float len = thickness; + float orientation = direction; + + vec2 dir = vec2(0.0); + if (current_screen == prev_screen) { + dir = normalize(next_screen - current_screen); + } else if (current_screen == next_screen) { + dir = normalize (current_screen - prev_screen); + } else { + vec2 dirA = normalize (current_screen - prev_screen); + if (miter == 1) { + vec2 dirB = normalize(next_screen - current_screen); + //now compute the miter join normal and length + vec2 tangent = normalize(dirA + dirB); + vec2 perp = vec2(-dirA.y, dirA.x); + vec2 miter_vec = vec2(-tangent.y, tangent.x); + dir = tangent; + len = thickness / dot(miter_vec, perp); + } else { + dir = dirA; + } + } + + vec2 normal = vec2(-dir.y, dir.x); + normal *= len/2.0; + normal.x /= aspect; + + vec4 offset = vec4(normal * orientation, 0.0, 0.0); + gl_Position = current_proj + offset; + v_color0 = vec4(1.0, 0.0, 1.0, 1.0); +} diff --git a/src/modules/RenderModule.cc b/src/modules/RenderModule.cc index bbc1111..6e330ce 100644 --- a/src/modules/RenderModule.cc +++ b/src/modules/RenderModule.cc @@ -84,6 +84,7 @@ static void module_reload(struct module_state *state) { assert (camera != nullptr); SerializeBool (*gReadSerializer, "protot.RenderModule.draw_floor", gRenderer->drawFloor); + SerializeBool (*gReadSerializer, "protot.RenderModule.draw_skybox", gRenderer->drawSkybox); SerializeBool (*gReadSerializer, "protot.RenderModule.debug_enabled", gRenderer->drawDebug); SerializeVec3 (*gReadSerializer, "protot.RenderModule.camera.eye", camera->eye); SerializeVec3 (*gReadSerializer, "protot.RenderModule.camera.poi", camera->poi); @@ -97,6 +98,7 @@ static void module_unload(struct module_state *state) { //(*gSerializer)["protot"]["RenderModule"]["active_camera"] = (double)gRenderer->activeCameraIndex; SerializeBool (*gWriteSerializer, "protot.RenderModule.draw_floor", gRenderer->drawFloor); + SerializeBool (*gWriteSerializer, "protot.RenderModule.draw_skybox", gRenderer->drawSkybox); SerializeBool (*gWriteSerializer, "protot.RenderModule.debug_enabled", gRenderer->drawDebug); SerializeVec3 (*gWriteSerializer, "protot.RenderModule.camera.eye", camera->eye); SerializeVec3 (*gWriteSerializer, "protot.RenderModule.camera.poi", camera->poi); @@ -149,7 +151,7 @@ bgfx::DynamicIndexBufferHandle debug_lines_ibh; bgfx::UniformHandle u_time; bgfx::UniformHandle u_color; -bgfx::UniformHandle u_lineparams; +bgfx::UniformHandle u_line_params; bgfx::UniformHandle u_mtx; bgfx::UniformHandle u_exposure; @@ -432,9 +434,7 @@ RenderState s_renderStates[RenderState::Count] = { | BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_DEPTH_WRITE - | BGFX_STATE_DEPTH_TEST_LESS -// | BGFX_STATE_CULL_CCW -// | BGFX_STATE_PT_LINESTRIP + | BGFX_STATE_DEPTH_TEST_ALWAYS | BGFX_STATE_MSAA, 0, RenderProgram(), @@ -449,6 +449,7 @@ RenderState s_renderStates[RenderState::Count] = { | BGFX_STATE_DEPTH_TEST_LESS | BGFX_STATE_CULL_CCW | BGFX_STATE_PT_LINES +// | BGFX_STATE_PT_POINTS | BGFX_STATE_MSAA, 0, RenderProgram(), @@ -552,6 +553,32 @@ struct PosColorTexCoord0Vertex bgfx::VertexDecl PosColorTexCoord0Vertex::ms_decl; +// Used for lines +struct PathVertex +{ + float position[3]; + float prev[3]; + float next[3]; + // TODO: use an int for the direction + float direction; + + static void init() + { + ms_decl + .begin() + .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::TexCoord0, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::TexCoord1, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::TexCoord2, 1, bgfx::AttribType::Float) + .end(); + } + + static bgfx::VertexDecl ms_decl; +}; +bgfx::VertexDecl PathVertex::ms_decl; + + + // // Static geometries // @@ -755,6 +782,7 @@ void Renderer::createGeometries() { PosNormalVertex::init(); PosNormalColorTexcoordVertex::init(); PosColorTexCoord0Vertex::init(); + PathVertex::init(); // Create static vertex buffer. cube_vbh = bgfx::createVertexBuffer( @@ -775,6 +803,18 @@ void Renderer::createGeometries() { bgfx::makeRef(s_cubeEdgeIndices, sizeof(s_cubeEdgeIndices) ) ); + // Create dynamic debug line buffer + path_lines_vbh = bgfx::createDynamicVertexBuffer( + (uint32_t) 1, + PathVertex::ms_decl, + BGFX_BUFFER_ALLOW_RESIZE + ); + + path_lines_ibh= bgfx::createDynamicIndexBuffer( + (uint32_t) 1, + BGFX_BUFFER_ALLOW_RESIZE + ); + // Create dynamic debug line buffer debug_lines_vbh = bgfx::createDynamicVertexBuffer( (uint32_t) 1, @@ -841,7 +881,7 @@ void Renderer::setupShaders() { u_time = bgfx::createUniform("u_time", bgfx::UniformType::Vec4); u_color = bgfx::createUniform("u_color", bgfx::UniformType::Vec4); - u_lineparams = bgfx::createUniform("u_lineparams", bgfx::UniformType::Vec4); + u_line_params = bgfx::createUniform("u_line_params", bgfx::UniformType::Vec4); m_timeOffset = bx::getHPCounter(); @@ -904,7 +944,7 @@ void Renderer::setupShaders() { lights[0].shadowMapFB = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true); } - s_renderStates[RenderState::Lines].m_program = RenderProgram("shaders/src/vs_lines.sc", "shaders/src/fs_lines.sc"); + s_renderStates[RenderState::Lines].m_program = RenderProgram("shaders/lines/vs_lines.sc", "shaders/lines/fs_lines.sc"); s_renderStates[RenderState::Debug].m_program = RenderProgram("shaders/src/vs_debug.sc", "shaders/src/fs_debug.sc"); } @@ -1087,7 +1127,7 @@ void Renderer::shutdown() { bgfx::destroyUniform(u_time); bgfx::destroyUniform(u_color); - bgfx::destroyUniform(u_lineparams); + bgfx::destroyUniform(u_line_params); for (uint8_t ii = 0; ii < RenderState::Count; ++ii) { if (bgfx::isValid(s_renderStates[ii].m_program.program)) { @@ -1279,7 +1319,7 @@ void Renderer::paintGL() { // Clear backbuffer and shadowmap framebuffer at beginning. bgfx::setViewClear(RenderState::Skybox , BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH - , 0xf03030ff, 1.0f, 0 + , 0x000000ff, 1.0f, 0 ); bgfx::setViewClear(RenderState::ShadowMap @@ -1295,29 +1335,31 @@ void Renderer::paintGL() { bgfx::touch(RenderState::Scene); bgfx::touch(RenderState::Skybox); - // Skybox pass - memcpy (IBL::uniforms.m_cameraPos, cameras[activeCameraIndex].eye.data(), 3 * sizeof(float)); + if (drawSkybox) { + // Skybox pass + memcpy (IBL::uniforms.m_cameraPos, cameras[activeCameraIndex].eye.data(), 3 * sizeof(float)); - const float amount = bx::fmin(0.012/0.12f, 1.0f); - IBL::settings.m_envRotCurr = bx::flerp(IBL::settings.m_envRotCurr, IBL::settings.m_envRotDest, amount); + const float amount = bx::fmin(0.012/0.12f, 1.0f); + IBL::settings.m_envRotCurr = bx::flerp(IBL::settings.m_envRotCurr, IBL::settings.m_envRotDest, amount); - float mtxEnvRot[16]; - float env_rot_cur = 0.0f; - float mtx_u_mtx[16]; + float mtxEnvRot[16]; + float env_rot_cur = 0.0f; + float mtx_u_mtx[16]; - bx::mtxRotateY(mtxEnvRot, env_rot_cur); - bx::mtxMul(IBL::uniforms.m_mtx, cameras[activeCameraIndex].mtxEnv, mtxEnvRot); // Used for Skybox. + bx::mtxRotateY(mtxEnvRot, env_rot_cur); + bx::mtxMul(IBL::uniforms.m_mtx, cameras[activeCameraIndex].mtxEnv, mtxEnvRot); // Used for Skybox. - bgfx::setTexture(0, s_texCube, mLightProbes[mCurrentLightProbe].m_tex); - bgfx::setTexture(1, s_texCubeIrr, mLightProbes[mCurrentLightProbe].m_texIrr); - bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); - screenSpaceQuad( - (float)cameras[activeCameraIndex].width, - (float)cameras[activeCameraIndex].height, true); + bgfx::setTexture(0, s_texCube, mLightProbes[mCurrentLightProbe].m_tex); + bgfx::setTexture(1, s_texCubeIrr, mLightProbes[mCurrentLightProbe].m_texIrr); + bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); + screenSpaceQuad( + (float)cameras[activeCameraIndex].width, + (float)cameras[activeCameraIndex].height, true); - IBL::uniforms.submit(); - bgfx::submit(RenderState::Skybox, s_renderStates[RenderState::Skybox].m_program.program); + IBL::uniforms.submit(); + bgfx::submit(RenderState::Skybox, s_renderStates[RenderState::Skybox].m_program.program); + } if (drawFloor) { @@ -1374,6 +1416,109 @@ void Renderer::paintGL() { meshSubmit(entities[i]->mesh, &s_renderStates[RenderState::Scene], 1, entities[i]->transform); } + // drawLinesHere + { + Path test_path; + + test_path.points.push_back(Vector3f (0.f, -1.f, 0.f)); + test_path.points.push_back(Vector3f (1.f, -1.f, 0.f)); + test_path.points.push_back(Vector3f (0.f, 0.f, 0.f)); + test_path.points.push_back(Vector3f (1.f, 0.f, 0.f)); + test_path.points.push_back(Vector3f (0.25f, -0.75f, 0.f)); + + // create an array for the actual buffer + std::vector path_vertices; + + // note: we submit each vertex twice + for (int i = 0; i < test_path.points.size(); i++) { + PathVertex vertex; + memcpy (vertex.position, test_path.points[i].data(), sizeof(float) * 3); + if (i == 0) { + assert (test_path.points.size() > 1); + memcpy (vertex.prev, test_path.points[i].data(), sizeof(float) * 3); + memcpy (vertex.next, test_path.points[i + 1].data(), sizeof(float) * 3); + } else if (i == test_path.points.size() - 1) { + memcpy (vertex.next, test_path.points[i].data(), sizeof(float) * 3); + memcpy (vertex.prev, test_path.points[i - 1].data(), sizeof(float) * 3); + } else { + memcpy (vertex.prev, test_path.points[i - 1].data(), sizeof(float) * 3); + memcpy (vertex.next, test_path.points[i + 1].data(), sizeof(float) * 3); + } + vertex.direction = -1.0f; + path_vertices.push_back(vertex); + vertex.direction = 1.0f; + path_vertices.push_back(vertex); + } + +// PathVertex* v = (PathVertex*) path_vertices.data(); +// int vi = 0; +// while (vi < path_vertices.size()) { +// cout << vi << ": v=" << v->position[0] << ", " << v->position[1] << ", " << v->position[2] +// << " p=" << v->prev[0] << ", " << v->prev[1] << ", " << v->prev[2] << ", " +// << " n=" << v->next[0] << ", " << v->next[1] << ", " << v->next[2] << ", " +// << " d=" << v->direction << endl; +// +// v++; +// vi++; +// } + + // update buffer from buffer data + bgfx::updateDynamicVertexBuffer (path_lines_vbh, + 0, + bgfx::copy(path_vertices.data(), sizeof(PathVertex) * path_vertices.size()) + ); + + std::vector line_indices; + int index = 0; + for (int i = 0; i < test_path.points.size() - 1; i++) { + int j = index; + line_indices.push_back(j + 0); + line_indices.push_back(j + 1); + line_indices.push_back(j + 2); + line_indices.push_back(j + 2); + line_indices.push_back(j + 1); + line_indices.push_back(j + 3); + index += 2; + } + +// for (int i = 0; i < line_indices.size(); i++) { +// cout << line_indices[i] << ", "; +// } +// cout << endl; +// +// cout << "points: " << test_path.points.size() +// << ", line indices: " << line_indices.size() +// << ", path_vertices: " << path_vertices.size() +// << ", last line index: " << line_indices[line_indices.size() -1] +// << ", width = " << width << ", height = " << height +// << endl; + +// assert (line_indices[line_indices.size() -1] < path_vertices.size()); +// assert (line_indices.size() == test_path.points.size() * 3); + + bgfx::updateDynamicIndexBuffer (path_lines_ibh, + 0, + bgfx::copy(line_indices.data(), sizeof(uint16_t) * line_indices.size()) + ); + + // submit data + const RenderState& st = s_renderStates[RenderState::Lines]; + + float thickness = 0.1f; + float miter = 1.f; + float aspect = width / height; + + Vector4f params (thickness, miter, width, height); + + Camera &active_camera = cameras[activeCameraIndex]; + + bgfx::setUniform(u_line_params, params.data(), 1); + bgfx::setIndexBuffer(path_lines_ibh); + bgfx::setVertexBuffer(path_lines_vbh); + bgfx::setState(st.m_state); + bgfx::submit(st.m_viewId, st.m_program.program); + } + // render debug information if (drawDebug) { float tmp[16]; @@ -1495,7 +1640,7 @@ void Renderer::paintGL() { width, height); - ImGui::SetNextWindowSize (ImVec2(400.f, 200.0f), ImGuiSetCond_Once); + ImGui::SetNextWindowSize (ImVec2(400.f, 300.0f), ImGuiSetCond_Once); ImGui::SetNextWindowPos (ImVec2(10.f, 300.0f), ImGuiSetCond_Once); ImGui::Begin("Render Settings"); @@ -1520,6 +1665,7 @@ void Renderer::paintGL() { assert (lights.size() == 1); ImGui::Checkbox("Draw Floor", &drawFloor); + ImGui::Checkbox("Draw Skybox", &drawSkybox); ImGui::Checkbox("Draw Debug", &drawDebug); for (int i = 0; i < lights.size(); i++) { diff --git a/src/modules/RenderModule.h b/src/modules/RenderModule.h index 200d192..cf0dfdf 100644 --- a/src/modules/RenderModule.h +++ b/src/modules/RenderModule.h @@ -176,6 +176,10 @@ struct LightProbe bgfx::TextureHandle m_texIrr; }; +struct Path { + std::vector points; +}; + struct DebugCommand { enum CommandType { Line, @@ -194,6 +198,7 @@ struct Renderer { bool initialized; bool drawDebug; bool drawFloor = true; + bool drawSkybox = true; uint32_t width; uint32_t height; diff --git a/src/modules/RenderUtils.cc b/src/modules/RenderUtils.cc index 8881fb9..c025d40 100644 --- a/src/modules/RenderUtils.cc +++ b/src/modules/RenderUtils.cc @@ -215,20 +215,25 @@ bgfx::ProgramHandle loadProgram(const char* _vsName, const char* _fsName) bgfx::ProgramHandle loadProgramFromFiles(const char *_vsFileName, const char *_fsFileName) { std::cout << "Loading shader " << _vsFileName << std::endl; - const char* argv[11]; + const char* argv[10]; argv[0] = "--type"; argv[1] = "vertex"; argv[2] = "--platform"; argv[3] = "linux"; argv[4] = "-i"; argv[5] = "shaders/common"; - argv[6] = "--varyingdef"; - argv[7] = "-p"; - argv[8] = "120"; - argv[9] = "-f"; - argv[10] = _vsFileName; + argv[6] = "-p"; + argv[7] = "120"; + argv[8] = "-f"; + argv[9] = _vsFileName; - bx::CommandLine cmdLine (11, argv); +// argv[6] = "--varyingdef"; +// argv[7] = "-p"; +// argv[8] = "120"; +// argv[9] = "-f"; +// argv[10] = _vsFileName; + + bx::CommandLine cmdLine (10, argv); const bgfx::Memory* vs_source_memory = loadMem(entry::getFileReader(), _vsFileName); bx::ReaderSeekerI* vs_source_reader = new bx::MemoryReader (vs_source_memory->data, vs_source_memory->size);