TESTGLSLGEOM: added geometry shader test application

also only regenerate the shader headers if something really changed for the c++ interface
added ScopedVertexBuffer
moved general imgui controls into TestApp
changed default gl versions
improved geometry shader support
master
Martin Gerhardy 2018-04-13 21:11:43 +02:00
parent 85d0a3b582
commit 4c0e4d1ce5
43 changed files with 523 additions and 306 deletions

2
.gitignore vendored
View File

@ -8,3 +8,5 @@
gmon.out
/*.sync
/perf.data*
luac.out
*.patch

View File

@ -167,7 +167,7 @@ doc: cmake
$(call COMPILE, codegen)
$(call COMPILE, $@)
server client voxedit shapetool mapedit shadertool noisetool databasetool uitool tests tests-math tests-core tests-persistence tests-voxel benchmarks-voxel tests-noise tests-computeshadertool testmesh testcamera testdepthbuffer testnuklear testtexture testvoxelfont testplane testimgui testoctree testglslcomp testluaui testoctreevisit testshapebuilder tests-shadertool flatc computeshadertool: cmake
server client voxedit shapetool mapedit shadertool noisetool databasetool uitool tests tests-math tests-core tests-persistence tests-voxel benchmarks-voxel tests-noise tests-computeshadertool testmesh testcamera testdepthbuffer testnuklear testtexture testvoxelfont testplane testimgui testoctree testglslgeom testglslcomp testluaui testoctreevisit testshapebuilder tests-shadertool flatc computeshadertool: cmake
$(call COMPILE, $@)
$(call COMPILE, copy-data-shared)
$(call COMPILE, copy-data-$@)

View File

@ -14,10 +14,6 @@ INFO: (0) Validation output: shaders/world
active samplers with a different type refer to the same texture image unit
```
## Code generation
Only replace the files if something has really changed. (`configure_file`?)
# Data handling
The current approach with data dir must be extended/redone someone. There are way too many files installed per artifact atm. Also there should be CPack support to generate debian packages.

View File

@ -48,115 +48,122 @@ endmacro()
macro(generate_shaders TARGET)
set(files ${ARGV})
list(REMOVE_AT files 0)
set(_headers)
set(GEN_DIR ${GENERATE_DIR}/shaders/${TARGET}/)
set(_template ${ROOT_DIR}/src/tools/shadertool/ShaderTemplate.h.in)
set(_template_ub ${ROOT_DIR}/src/tools/shadertool/UniformBufferTemplate.h.in)
file(MAKE_DIRECTORY ${GEN_DIR})
target_include_directories(${TARGET} PUBLIC ${GEN_DIR})
foreach (shader_dir "${TARGET}" shared)
set(_dir ${ROOT_DIR}/${GAME_BASE_DIR}/${shader_dir}/shaders)
if (IS_DIRECTORY ${_dir})
foreach (_file ${files})
convert_to_camel_case(${_file} _f)
set(_shaderfile "${_f}Shader.h")
set(_shader "${GEN_DIR}${_shaderfile}")
if (EXISTS ${_dir}/${_file}.frag AND EXISTS ${_dir}/${_file}.vert)
add_custom_command(
OUTPUT ${_shader}
IMPLICIT_DEPENDS C ${_dir}/${_file}.frag C ${_dir}/${_file}.vert
COMMENT "Validate ${_file} and generate ${_shaderfile}"
COMMAND ${CMAKE_BINARY_DIR}/shadertool --glslang ${CMAKE_BINARY_DIR}/glslangValidator --shader ${_dir}/${_file} --shadertemplate ${_template} --buffertemplate ${_template_ub} --sourcedir ${GEN_DIR}
DEPENDS shadertool ${_dir}/${_file}.frag ${_dir}/${_file}.vert ${_template} ${_template_ub}
)
list(APPEND _headers ${_shader})
elseif (EXISTS ${_dir}/${_file}.comp)
add_custom_command(
OUTPUT ${_shader}
IMPLICIT_DEPENDS C ${_dir}/${_file}.comp
COMMENT "Validate ${_file} and generate ${_shaderfile}"
COMMAND ${CMAKE_BINARY_DIR}/shadertool --glslang ${CMAKE_BINARY_DIR}/glslangValidator --shader ${_dir}/${_file} --shadertemplate ${_template} --buffertemplate ${_template_ub} --sourcedir ${GEN_DIR}
DEPENDS shadertool ${_dir}/${_file}.comp ${_template} ${_template_ub}
)
list(APPEND _headers ${_shader})
endif()
endforeach()
set(_headers)
add_custom_target(UpdateShaders${TARGET})
file(WRITE ${CMAKE_BINARY_DIR}/GenerateShaderHeader${TARGET}.cmake "configure_file(\${SRC} \${DST} @ONLY)")
foreach (_file ${files})
set(_shaders)
set(_lastdir)
foreach (shader_dir "${TARGET}" shared)
set(_dir ${ROOT_DIR}/${GAME_BASE_DIR}/${shader_dir}/shaders)
if (EXISTS ${_dir}/${_file}.frag AND EXISTS ${_dir}/${_file}.vert)
list(APPEND _shaders ${_dir}/${_file}.frag ${_dir}/${_file}.vert)
set(_lastdir ${_dir})
endif()
if (EXISTS ${_dir}/${_file}.geom)
list(APPEND _shaders ${_dir}/${_file}.geom)
set(_lastdir ${_dir})
endif()
if (EXISTS ${_dir}/${_file}.comp)
list(APPEND _shaders ${_dir}/${_file}.comp)
set(_lastdir ${_dir})
endif()
endforeach()
if (_shaders)
convert_to_camel_case(${_file} _f)
set(_shaderfile "${_f}Shader.h")
set(_shader "${GEN_DIR}${_shaderfile}")
add_custom_command(
OUTPUT ${_shader}.in
IMPLICIT_DEPENDS C ${_shaders}
COMMENT "Validate ${_file} and generate ${_shaderfile}"
COMMAND ${CMAKE_BINARY_DIR}/shadertool --glslang ${CMAKE_BINARY_DIR}/glslangValidator --postfix .in --shader ${_lastdir}/${_file} --shadertemplate ${_template} --buffertemplate ${_template_ub} --sourcedir ${GEN_DIR}
DEPENDS shadertool ${_shaders} ${_template} ${_template_ub}
)
list(APPEND _headers ${_shader})
add_custom_command(OUTPUT ${_shader} COMMAND ${CMAKE_COMMAND} -D SRC=${_shader}.in -D DST=${_shader} -P ${CMAKE_BINARY_DIR}/GenerateShaderHeader${TARGET}.cmake DEPENDS ${_shader}.in)
else()
message(FATAL_ERROR "Could not find any shader files for ${_file} and target '${TARGET}'")
endif()
endforeach()
convert_to_camel_case(${TARGET} _filetarget)
# TODO: not regenerated if files were added, renamed or removed
set(_h ${GEN_DIR}/${_filetarget}Shaders.h)
file(WRITE ${_h}.in "#pragma once\n")
foreach(header_path ${_headers})
foreach (header_path ${_headers})
string(REPLACE "${GEN_DIR}" "" header "${header_path}")
file(APPEND ${_h}.in "#include \"${header}\"\n")
endforeach()
add_custom_command(
OUTPUT ${_h}
COMMAND ${CMAKE_COMMAND}
ARGS -E copy_if_different ${_h}.in ${_h}
COMMENT "Generate ${_h}"
)
add_custom_target(GenerateShaderBindings${TARGET}
DEPENDS ${_headers} ${_h}
DEPENDS ${_headers}
COMMENT "Generate shader bindings for ${TARGET} in ${GEN_DIR}"
)
#target_sources(${TARGET} PUBLIC ${_headers} ${_h})
set_source_files_properties(${_headers} ${_h} ${_h}.in PROPERTIES GENERATED TRUE)
add_dependencies(${TARGET} GenerateShaderBindings${TARGET})
add_dependencies(codegen GenerateShaderBindings${TARGET})
set_source_files_properties(${_headers} ${_h} PROPERTIES GENERATED TRUE)
add_custom_target(GenerateShaderHeader${TARGET} ${CMAKE_COMMAND} -D SRC=${_h}.in -D DST=${_h} -P ${CMAKE_BINARY_DIR}/GenerateShaderHeader${TARGET}.cmake)
add_dependencies(${TARGET} GenerateShaderHeader${TARGET} UpdateShaders${TARGET})
add_dependencies(GenerateShaderHeader${TARGET} GenerateShaderBindings${TARGET})
add_dependencies(codegen GenerateShaderHeader${TARGET} UpdateShaders${TARGET})
endmacro()
macro(generate_compute_shaders TARGET)
set(files ${ARGV})
list(REMOVE_AT files 0)
set(_headers)
set(GEN_DIR ${GENERATE_DIR}/compute-shaders/${TARGET}/)
set(_template ${ROOT_DIR}/src/tools/computeshadertool/ComputeShaderTemplate.h.in)
file(MAKE_DIRECTORY ${GEN_DIR})
target_include_directories(${TARGET} PUBLIC ${GEN_DIR})
foreach (shader_dir "${TARGET}" shared)
set(_dir ${ROOT_DIR}/${GAME_BASE_DIR}/${shader_dir}/shaders)
if (IS_DIRECTORY ${_dir})
foreach (_file ${files})
if (EXISTS ${_dir}/${_file}.cl)
convert_to_camel_case(${_file} _f)
set(_shaderfile "${_f}Shader.h")
set(_shader "${GEN_DIR}${_shaderfile}")
add_custom_command(
OUTPUT ${_shader}
IMPLICIT_DEPENDS C ${_dir}/${_file}.cl
COMMENT "Generate ${_shaderfile}"
COMMAND ${CMAKE_BINARY_DIR}/computeshadertool --shader ${_dir}/${_file} --shadertemplate ${_template} --sourcedir ${GEN_DIR}
DEPENDS computeshadertool ${_dir}/${_file}.cl ${_template}
)
list(APPEND _headers ${_shader})
endif()
endforeach()
set(_headers)
add_custom_target(UpdateComputeShaders${TARGET})
file(WRITE ${CMAKE_BINARY_DIR}/GenerateComputeShaderHeader${TARGET}.cmake "configure_file(\${SRC} \${DST} @ONLY)")
foreach (_file ${files})
set(_shaders)
set(_lastdir)
foreach (shader_dir "${TARGET}" shared)
set(_dir ${ROOT_DIR}/${GAME_BASE_DIR}/${shader_dir}/shaders)
if (EXISTS ${_dir}/${_file}.cl)
list(APPEND _shaders ${_dir}/${_file}.cl)
set(_lastdir ${_dir})
endif()
endforeach()
if (_shaders)
convert_to_camel_case(${_file} _f)
set(_shaderfile "${_f}Shader.h")
set(_shader "${GEN_DIR}${_shaderfile}")
add_custom_command(
OUTPUT ${_shader}.in
IMPLICIT_DEPENDS C ${_shaders}
COMMENT "Validate ${_file} and generate ${_shaderfile}"
COMMAND ${CMAKE_BINARY_DIR}/computeshadertool --shader ${_dir}/${_file} --postfix .in --shadertemplate ${_template} --sourcedir ${GEN_DIR}
DEPENDS computeshadertool ${_shaders} ${_template}
)
list(APPEND _headers ${_shader})
add_custom_command(OUTPUT ${_shader} COMMAND ${CMAKE_COMMAND} -D SRC=${_shader}.in -D DST=${_shader} -P ${CMAKE_BINARY_DIR}/GenerateComputeShaderHeader${TARGET}.cmake DEPENDS ${_shader}.in)
else()
message(FATAL_ERROR "Could not find any shader files for ${_file} and target '${TARGET}'")
endif()
endforeach()
convert_to_camel_case(${TARGET} _filetarget)
# TODO: not regenerated if files were added, renamed or removed
set(_h ${GEN_DIR}/${_filetarget}Shaders.h)
file(WRITE ${_h}.in "#pragma once\n")
foreach(header_path ${_headers})
foreach (header_path ${_headers})
string(REPLACE "${GEN_DIR}" "" header "${header_path}")
file(APPEND ${_h}.in "#include \"${header}\"\n")
endforeach()
add_custom_command(
OUTPUT ${_h}
COMMAND ${CMAKE_COMMAND}
ARGS -E copy_if_different ${_h}.in ${_h}
COMMENT "Generate ${_h}"
)
add_custom_target(GenerateComputeShaderBindings${TARGET}
DEPENDS ${_headers} ${_h}
COMMENT "Generate compute shader bindings for ${TARGET} in ${GEN_DIR}"
DEPENDS ${_headers}
COMMENT "Generate shader bindings for ${TARGET} in ${GEN_DIR}"
)
#target_sources(${TARGET} PUBLIC ${_headers} ${_h})
set_source_files_properties(${_headers} ${_h} ${_h}.in PROPERTIES GENERATED TRUE)
add_dependencies(${TARGET} GenerateComputeShaderBindings${TARGET})
add_dependencies(codegen GenerateComputeShaderBindings${TARGET})
set_source_files_properties(${_headers} ${_h} PROPERTIES GENERATED TRUE)
add_custom_target(GenerateComputeShaderHeader${TARGET} ${CMAKE_COMMAND} -D SRC=${_h}.in -D DST=${_h} -P ${CMAKE_BINARY_DIR}/GenerateComputeShaderHeader${TARGET}.cmake)
add_dependencies(${TARGET} GenerateComputeShaderHeader${TARGET} UpdateComputeShaders${TARGET})
add_dependencies(GenerateComputeShaderHeader${TARGET} GenerateComputeShaderBindings${TARGET})
add_dependencies(codegen GenerateComputeShaderHeader${TARGET} UpdateComputeShaders${TARGET})
endmacro()
macro(generate_db_models TARGET INPUT OUTPUT)

View File

@ -0,0 +1,6 @@
$in vec3 v_color;
$out vec4 o_color;
void main() {
o_color = vec4(v_color, 1.0);
}

View File

@ -0,0 +1,26 @@
layout(points) in;
layout(line_strip, max_vertices = 64) out;
$in vec3 g_color[];
$out vec3 v_color;
uniform int u_sides;
uniform float u_radius;
uniform mat4 u_projection;
const float PI = 3.1415926;
void main() {
v_color = g_color[0];
float delta = PI * 2.0 / float(u_sides);
float ang = 0.0f;
for (int i = 0; i <= u_sides; i++) {
vec4 offset = vec4(cos(ang) * u_radius, -sin(ang) * u_radius, 0.0, 0.0);
gl_Position = u_projection * (gl_in[0].gl_Position + offset);
ang += delta;
EmitVertex();
}
EndPrimitive();
}

View File

@ -0,0 +1,9 @@
$in vec4 a_pos;
$in vec3 a_color;
uniform mat4 u_view;
$out vec3 g_color;
void main() {
gl_Position = u_view * a_pos;
g_color = a_color;
}

View File

@ -0,0 +1,5 @@
w +move_forward
a +move_left
s +move_backward
d +move_right
ctrl+q quit

View File

@ -38,10 +38,9 @@ void TextureRenderer::render(const glm::mat4& projection) {
video::ScopedShader scoped(_textureShader);
_textureShader.setProjection(projection);
_textureShader.setTexture(video::TextureUnit::Zero);
_texturedFullscreenQuad.bind();
video::ScopedVertexBuffer scopedBuf(_texturedFullscreenQuad);
const int elements = _texturedFullscreenQuad.elements(0, _textureShader.getComponentsPos());
video::drawArrays(video::Primitive::Triangles, elements);
_texturedFullscreenQuad.unbind();
}
void TextureRenderer::shutdown() {

View File

@ -115,6 +115,19 @@ void TestApp::onRenderUI() {
if (ImGui::Checkbox("Toggle profiler", &temp)) {
_renderTracing = toggleTrace();
}
if (ImGui::Checkbox("Render axis", &_renderAxis)) {
setRenderAxis(_renderAxis);
}
if (ImGui::Checkbox("Render plane", &_renderPlane)) {
setRenderPlane(_renderPlane);
}
if (ImGui::Checkbox("Camera motion", &_cameraMotion)) {
setCameraMotion(_cameraMotion);
}
if (ImGui::InputFloat("Camera speed", &_cameraSpeed, 0.02f, 0.1f)) {
setCameraSpeed(_cameraSpeed);
}
ImGui::InputVarFloat("Rotation speed", _rotationSpeed, 0.01f, 0.1f);
ImGui::Separator();
if (ImGui::Button("Quit")) {
requestQuit();

View File

@ -145,9 +145,6 @@ void TestMeshApp::onRenderUI() {
ImGui::CheckboxVar("Show shadow cascades", _debugShadowCascade);
static const char* items[] = { "Disable", "First", "Second", "Third", "Fourth" };
ImGui::Combo("Bone weight", &_boneInfluence, items, IM_ARRAYSIZE(items));
if (ImGui::Checkbox("Render axis", &_renderAxis)) {
setRenderAxis(_renderAxis);
}
ImGui::Checkbox("Render mesh", &_renderMesh);
ImGui::Checkbox("Render normals", &_renderNormals);
ImGui::Checkbox("Render bones", &_renderBones);
@ -158,15 +155,6 @@ void TestMeshApp::onRenderUI() {
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
if (ImGui::Checkbox("Render plane", &_renderPlane)) {
setRenderPlane(_renderPlane);
}
if (ImGui::Checkbox("Camera motion", &_cameraMotion)) {
setCameraMotion(_cameraMotion);
}
if (ImGui::InputFloat("Camera speed", &_cameraSpeed, 0.02f, 0.1f)) {
setCameraSpeed(_cameraSpeed);
}
if (ImGui::InputFloat3("Camera omega", glm::value_ptr(_omega))) {
_camera.setOmega(_omega);
}
@ -174,7 +162,6 @@ void TestMeshApp::onRenderUI() {
ImGui::InputFloat("Shadow bias slope", &_shadowBiasSlope, 0.01f, 0.1f);
ImGui::InputFloat("Shadow range", &_shadowRangeZ, 0.01f, 0.1f);
ImGui::InputFloat("Fog range", &_fogRange, 0.01f, 0.1f);
ImGui::InputVarFloat("Rotation speed", _rotationSpeed, 0.01f, 0.1f);
if (_mesh->animations() > 1 && ImGui::InputVarInt("Animation index", _animationIndex, 1, 1)) {
_animationIndex->setVal(_mesh->currentAnimation());
}
@ -320,7 +307,7 @@ void TestMeshApp::doRender() {
_shadowMapRenderShader.setNear(_camera.nearPlane());
// bind buffers
core_assert_always(_shadowMapDebugBuffer.bind());
video::ScopedVertexBuffer scopedBuf(_shadowMapDebugBuffer);
// configure shadow map texture
video::bindTexture(video::TextureUnit::Zero, _depthBuffer);
@ -341,9 +328,6 @@ void TestMeshApp::doRender() {
if (_depthBuffer.depthCompare()) {
video::setupDepthCompareTexture(video::TextureUnit::Zero, _depthBuffer.textureType(), _depthBuffer.texture());
}
// unbind buffer
_shadowMapDebugBuffer.unbind();
}
if (!oldDepth) {

View File

@ -342,7 +342,7 @@ core::AppState IMGUIApp::onRunning() {
core_assert_always(_vbo.update(_bufferIndex, cmdList->VtxBuffer.Data, cmdList->VtxBuffer.Size * sizeof(ImDrawVert)));
core_assert_always(_vbo.update(_indexBufferIndex, cmdList->IdxBuffer.Data, cmdList->IdxBuffer.Size * sizeof(ImDrawIdx)));
core_assert_always(_vbo.bind());
video::ScopedVertexBuffer scopedBuf(_vbo);
for (int i = 0; i < cmdList->CmdBuffer.Size; ++i) {
const ImDrawCmd* cmd = &cmdList->CmdBuffer[i];
@ -356,7 +356,6 @@ core::AppState IMGUIApp::onRunning() {
}
idxBufferOffset += cmd->ElemCount;
}
_vbo.unbind();
}
video::scissor(0, 0, renderTargetW, renderTargetH);

View File

@ -592,7 +592,7 @@ int Mesh::render() {
if (_state != io::IOSTATE_LOADED) {
return 0;
}
_vertexBuffer.bind();
video::ScopedVertexBuffer scopedBuf(_vertexBuffer);
int drawCalls = 0;
for (const RenderMeshData& mesh : _meshData) {
const uint32_t matIdx = mesh.materialIndex;
@ -602,8 +602,6 @@ int Mesh::render() {
video::drawElementsBaseVertex<Indices::value_type>(video::Primitive::Triangles, mesh.noOfIndices, mesh.baseIndex, mesh.baseVertex);
++drawCalls;
}
_vertexBuffer.unbind();
return drawCalls;
}
@ -638,11 +636,10 @@ int Mesh::renderBones(video::Shader& shader) {
boneData.reserve(_boneMapping.size() * 2);
traverseBones(boneData, _scene->mRootNode, glm::mat4(1.0f), glm::vec3(0), false);
_vertexBufferLines.update(_vertexBufferLinesIndex, boneData.data);
_vertexBufferLines.bind();
video::ScopedVertexBuffer scopedBuf(_vertexBufferLines);
ScopedLineWidth lineWidth(2.0f);
const int elements = _vertexBufferLines.elements(_vertexBufferLinesIndex, 2);
video::drawArrays(video::Primitive::Lines, elements);
_vertexBufferLines.unbind();
return 1;
}
@ -681,11 +678,10 @@ int Mesh::renderNormals(video::Shader& shader) {
}
_vertexBufferLines.update(_vertexBufferLinesIndex, normalData.data);
_vertexBufferLines.bind();
video::ScopedVertexBuffer scopedBuf(_vertexBufferLines);
ScopedLineWidth lineWidth(2.0f);
const int elements = _vertexBufferLines.elements(_vertexBufferLinesIndex, 2);
video::drawArrays(video::Primitive::Lines, elements);
_vertexBufferLines.unbind();
return 1;
}

View File

@ -17,12 +17,12 @@
namespace video {
#ifdef GL_ES_VERSION_2_0
#ifdef GL_ES_VERSION_3_1
// default to opengles3
int Shader::glslVersion = GLSLVersion::V300;
int Shader::glslVersion = GLSLVersion::V310;
#else
// default to opengl3
int Shader::glslVersion = GLSLVersion::V330;
// default to opengl4
int Shader::glslVersion = GLSLVersion::V430;
#endif
Shader::Shader() {
@ -327,14 +327,12 @@ std::string Shader::getSource(ShaderType shaderType, const std::string& buffer,
}
std::string src;
src.append("#version ");
if (shaderType == ShaderType::Compute) {
src.append("430");
} else {
src.append(std::to_string(glslVersion));
}
src.append(std::to_string(glslVersion));
src.append("\n");
if (glslVersion < GLSLVersion::V140) {
//src.append("#extension GL_EXT_draw_instanced : enable\n");
if (shaderType == ShaderType::Compute) {
src.append("#extension GL_ARB_compute_shader : enable\n");
src.append("#extension GL_ARB_shader_storage_buffer_object : enable\n");
src.append("#extension GL_ARB_compute_variable_group_size : enable\n");
}
core::Var::visitSorted([&] (const core::VarPtr& var) {

View File

@ -1,3 +1,7 @@
/**
* @file
*/
#include "ShaderManager.h"
#include "core/Var.h"
#include "core/Log.h"

View File

@ -9,6 +9,9 @@
namespace video {
/**
* Register @c Shader instances here to let them automatically recompile
* on @c core::CV_SHADER @c core::CVar change.
*
* @ingroup Video
*/
class ShaderManager {

View File

@ -144,7 +144,11 @@ enum class VertexBufferMode {
enum class Primitive {
Points,
Lines,
LinesAdjacency,
Triangles,
TrianglesAdjacency,
LineStrip,
TriangleStrip,
Max
};

View File

@ -170,4 +170,18 @@ inline void VertexBuffer::setMode(int32_t idx, VertexBufferMode mode) {
_modes[idx] = mode;
}
class ScopedVertexBuffer {
private:
const VertexBuffer& _buf;
public:
ScopedVertexBuffer(const VertexBuffer& buf) :
_buf(buf) {
buf.bind();
}
~ScopedVertexBuffer() {
_buf.unbind();
}
};
}

View File

@ -157,7 +157,11 @@ static_assert(std::enum_value(Face::Max) == lengthof(Faces), "Array sizes don't
static GLenum Primitives[] {
GL_POINTS,
GL_LINES,
GL_TRIANGLES
GL_LINES_ADJACENCY,
GL_TRIANGLES,
GL_TRIANGLES_ADJACENCY,
GL_LINE_STRIP,
GL_TRIANGLE_STRIP,
};
static_assert(std::enum_value(Primitive::Max) == lengthof(Primitives), "Array sizes don't match Max");

View File

@ -75,8 +75,6 @@ else()
target_compile_options(${LIB} PRIVATE -O3)
endif()
generate_compute_shaders(voxel meshextractor)
set(TEST_SRCS
tests/AbstractVoxelTest.h
tests/AbstractVoxFormatTest.h tests/AbstractVoxFormatTest.cpp

View File

@ -115,9 +115,8 @@ void OctreeRenderer::renderOctreeNode(const video::Camera& camera, RenderOctreeN
const int numIndices = renderNode->_vb.elements(renderNode->_indexBuffer, 1, sizeof(voxel::IndexType));
if (numIndices > 0 && renderNode->_renderThisNode) {
if (camera.isVisible(renderNode->_aabb)) {
renderNode->_vb.bind();
video::ScopedVertexBuffer scopedBuf(renderNode->_vb);
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices);
renderNode->_vb.unbind();
}
}

View File

@ -220,7 +220,7 @@ void RawVolumeRenderer::render(const video::Camera& camera) {
if (nIndices == 0) {
continue;
}
core_assert_always(_vertexBuffer[idx].bind());
video::ScopedVertexBuffer scopedBuf(_vertexBuffer[idx]);
_shadowMapShader.setModel(glm::translate(_offsets[idx]));
for (int i = 0; i < maxDepthBuffers; ++i) {
_depthBuffer.bindTexture(i);
@ -228,7 +228,6 @@ void RawVolumeRenderer::render(const video::Camera& camera) {
static_assert(sizeof(voxel::IndexType) == sizeof(uint32_t), "Index type doesn't match");
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, nIndices);
}
_vertexBuffer[idx].unbind();
}
video::cullFace(video::Face::Back);
if (oldBlend) {
@ -255,11 +254,10 @@ void RawVolumeRenderer::render(const video::Camera& camera) {
if (nIndices == 0) {
continue;
}
core_assert_always(_vertexBuffer[idx].bind());
video::ScopedVertexBuffer scopedBuf(_vertexBuffer[idx]);
_worldShader.setModel(glm::translate(_offsets[idx]));
static_assert(sizeof(voxel::IndexType) == sizeof(uint32_t), "Index type doesn't match");
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, nIndices);
_vertexBuffer[idx].unbind();
}
}
_whiteTexture->unbind();

View File

@ -339,9 +339,8 @@ bool WorldRenderer::renderOpaqueBuffers() {
if (numIndices == 0u) {
return false;
}
_opaqueBuffer.bind();
video::ScopedVertexBuffer scopedBuf(_opaqueBuffer);
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices);
_opaqueBuffer.unbind();
return true;
}
@ -350,9 +349,8 @@ bool WorldRenderer::renderWaterBuffers() {
if (numIndices == 0u) {
return false;
}
_waterBuffer.bind();
video::ScopedVertexBuffer scopedBuf(_waterBuffer);
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices);
_waterBuffer.unbind();
return true;
}
@ -364,7 +362,7 @@ int WorldRenderer::renderPlants(const std::list<PlantBuffer*>& vbos, int* vertic
continue;
}
vbo->vb.bind();
video::ScopedVertexBuffer scopedBuf(vbo->vb);
if (vbo->amount == 1) {
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices);
} else {
@ -557,7 +555,7 @@ int WorldRenderer::renderWorld(const video::Camera& camera, int* vertices) {
_shadowMapRenderShader.setNear(camera.nearPlane());
// bind buffers
core_assert_always(_shadowMapDebugBuffer.bind());
video::ScopedVertexBuffer scopedBuf(_shadowMapDebugBuffer);
// configure shadow map texture
video::bindTexture(video::TextureUnit::Zero, _depthBuffer);
@ -578,9 +576,6 @@ int WorldRenderer::renderWorld(const video::Camera& camera, int* vertices) {
if (_depthBuffer.depthCompare()) {
video::setupDepthCompareTexture(video::TextureUnit::Zero, _depthBuffer.textureType(), _depthBuffer.texture());
}
// unbind buffer
_shadowMapDebugBuffer.unbind();
}
if (_renderAABBs->boolVal()) {

View File

@ -3,6 +3,7 @@ add_subdirectory(testmesh)
add_subdirectory(testtexture)
add_subdirectory(testplane)
add_subdirectory(testglslcomp)
add_subdirectory(testglslgeom)
add_subdirectory(testimgui)
add_subdirectory(testnuklear)
add_subdirectory(testluaui)

View File

@ -15,11 +15,10 @@ void TestDepthBuffer::doRender() {
const int quadHeight = (int) (height / 3.0f);
video::ScopedShader scopedShader(_shadowMapRenderShader);
video::ScopedViewPort scopedViewport(width - quadWidth, 0, quadWidth, quadHeight);
core_assert_always(_texturedFullscreenQuad.bind());
video::ScopedVertexBuffer scopedBuf(_texturedFullscreenQuad);
video::bindTexture(video::TextureUnit::Zero, _depthBuffer);
_shadowMapRenderShader.setShadowmap(video::TextureUnit::Zero);
video::drawArrays(video::Primitive::Triangles, _texturedFullscreenQuad.elements(0));
_texturedFullscreenQuad.unbind();
}
core::AppState TestDepthBuffer::onInit() {

View File

@ -0,0 +1,7 @@
project(testglslgeom)
set(SRCS
TestGLSLGeom.h TestGLSLGeom.cpp
)
engine_add_executable(TARGET ${PROJECT_NAME} SRCS ${SRCS} WINDOWED NOINSTALL)
engine_target_link_libraries(TARGET ${PROJECT_NAME} DEPENDENCIES testcore imgui)
generate_shaders(${PROJECT_NAME} test)

View File

@ -0,0 +1,80 @@
/**
* @file
*/
#include "TestGLSLGeom.h"
#include "io/Filesystem.h"
#include "core/Color.h"
#include "video/Camera.h"
#include "video/ScopedViewPort.h"
TestGLSLGeom::TestGLSLGeom(const metric::MetricPtr& metric, const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus, const core::TimeProviderPtr& timeProvider) :
Super(metric, filesystem, eventBus, timeProvider) {
init(ORGANISATION, "testglslgeom");
}
core::AppState TestGLSLGeom::onInit() {
core::AppState state = Super::onInit();
if (state != core::AppState::Running) {
return state;
}
if (!_testShader.setup()) {
Log::error("Failed to init the compute shader");
return core::AppState::InitFailure;
}
_testShader.recordUsedUniforms(true);
struct Buf {
glm::vec4 pos{0, 0, 0, 1};
glm::vec3 color{1, 1, 1};
};
Buf buf;
int32_t bufIndex = _buffer.create(&buf, sizeof(buf));
_buffer.setMode(bufIndex, video::VertexBufferMode::Static);
video::Attribute attributePos;
attributePos.bufferIndex = bufIndex;
attributePos.index = _testShader.getLocationPos();
attributePos.size = _testShader.getComponentsPos();
attributePos.offset = offsetof(Buf, pos);
attributePos.stride = sizeof(Buf);
_buffer.addAttribute(attributePos);
video::Attribute attributeColor;
attributeColor.bufferIndex = bufIndex;
attributeColor.index = _testShader.getLocationColor();
attributeColor.size = _testShader.getComponentsColor();
attributeColor.offset = offsetof(Buf, color);
attributeColor.stride = sizeof(Buf);
_buffer.addAttribute(attributeColor);
video::clearColor(::core::Color::Black);
return state;
}
core::AppState TestGLSLGeom::onCleanup() {
core::AppState state = Super::onCleanup();
_testShader.shutdown();
_buffer.shutdown();
return state;
}
void TestGLSLGeom::onRenderUI() {
ImGui::SliderFloat("radius", &_radius, 1.0f, 20.0f);
ImGui::SliderInt("sides", &_sides, 2, _testShader.getMaxGeometryVertices());
Super::onRenderUI();
}
void TestGLSLGeom::doRender() {
video::ScopedShader scopedShd(_testShader);
_testShader.setSides(_sides);
_testShader.setRadius(_radius);
_testShader.setView(_camera.viewMatrix());
_testShader.setProjection(_camera.projectionMatrix());
video::ScopedVertexBuffer scopedBuf(_buffer);
const int elements = _buffer.elements(0, _testShader.getComponentsPos());
video::drawArrays(_testShader.getPrimitiveTypeIn(), elements);
}
TEST_APP(TestGLSLGeom)

View File

@ -0,0 +1,31 @@
/**
* @file
*/
#pragma once
#include "testcore/TestApp.h"
#include "video/VertexBuffer.h"
#include "TestglslgeomShaders.h"
/**
* @brief Visual test for GLSL geometry shaders
*
* This test application is using a geometry shader to build a sphere from a single point.
*/
class TestGLSLGeom: public TestApp {
private:
using Super = TestApp;
shader::TestShader _testShader;
video::VertexBuffer _buffer;
int _sides = 16;
float _radius = 10.0f;
void doRender() override;
public:
TestGLSLGeom(const metric::MetricPtr& metric, const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus, const core::TimeProviderPtr& timeProvider);
virtual void onRenderUI() override;
virtual core::AppState onInit() override;
virtual core::AppState onCleanup() override;
};

View File

@ -171,9 +171,6 @@ void TestShapeBuilder::onRenderUI() {
ImGui::Separator();
ImGui::Checkbox("Render Axis", &_renderAxis);
ImGui::Checkbox("Render Plane", &_renderPlane);
if (ImGui::Button("Clear")) {
for (int i = 0; i < _meshCount; ++i) {
_shapeRenderer.deleteMesh(_meshes[i]);

View File

@ -41,6 +41,7 @@ core::AppState ComputeShaderTool::onRunning() {
_shaderDirectory = getArgVal("--shaderdir");
_sourceDirectory = getArgVal("--sourcedir",
_filesystem->basePath() + "src/modules/" + _namespaceSrc + "/");
_postfix = getArgVal("--postfix", "");
if (!core::string::endsWith(_shaderDirectory, "/")) {
_shaderDirectory = _shaderDirectory + "/";
@ -68,7 +69,7 @@ core::AppState ComputeShaderTool::onRunning() {
return core::AppState::Cleanup;
}
const std::string& templateShader = filesystem()->load(_shaderTemplateFile);
if (!computeshadertool::generateSrc(filesystem(), templateShader, _name, _namespaceSrc, _shaderDirectory, _sourceDirectory, _kernels, _structs)) {
if (!computeshadertool::generateSrc(filesystem(), templateShader, _name, _namespaceSrc, _shaderDirectory, _sourceDirectory, _kernels, _structs, _postfix)) {
_exitCode = 100;
return core::AppState::Cleanup;
}

View File

@ -31,6 +31,7 @@ private:
protected:
std::string _namespaceSrc;
std::string _sourceDirectory;
std::string _postfix;
std::string _shaderDirectory;
std::string _computeFilename;
std::string _shaderTemplateFile;

View File

@ -214,7 +214,8 @@ bool generateSrc(const io::FilesystemPtr& filesystem,
const std::string& shaderDirectory,
const std::string& sourceDirectory,
const std::vector<Kernel>& _kernels,
const std::vector<Struct>& _structs) {
const std::vector<Struct>& _structs,
const std::string& postfix) {
const std::string name = _name + "Shader";
std::vector<std::string> shaderNameParts;
@ -267,7 +268,7 @@ bool generateSrc(const io::FilesystemPtr& filesystem,
src = core::string::replaceAll(src, "$shutdown$", shutdown.str());
src = core::string::replaceAll(src, "$structs$", structs.str());
src = core::string::replaceAll(src, "$createkernels$", createKernels.str());
const std::string targetFile = sourceDirectory + filename + ".h";
const std::string targetFile = sourceDirectory + filename + ".h" + postfix;
Log::info("Generate shader bindings for %s at %s", _name.c_str(), targetFile.c_str());
if (!filesystem->syswrite(targetFile, src)) {
Log::error("Failed to write %s", targetFile.c_str());

View File

@ -18,6 +18,7 @@ extern bool generateSrc(const io::FilesystemPtr& filesystem,
const std::string& sourceDirectory,
const std::string& templateShader,
const std::vector<Kernel>& kernels,
const std::vector<Struct>& structs);
const std::vector<Struct>& structs,
const std::string& postfix);
}

View File

@ -32,7 +32,7 @@ static const char *convertToTexUnit(int unit) {
}
bool generateSrc(const std::string& templateShader, const std::string& templateUniformBuffer, const ShaderStruct& shaderStruct,
const io::FilesystemPtr& filesystem, const std::string& namespaceSrc, const std::string& sourceDirectory, const std::string& shaderDirectory) {
const io::FilesystemPtr& filesystem, const std::string& namespaceSrc, const std::string& sourceDirectory, const std::string& shaderDirectory, const std::string& postfix) {
std::string src(templateShader);
const std::string& name = shaderStruct.name + "Shader";
@ -93,15 +93,30 @@ bool generateSrc(const std::string& templateShader, const std::string& templateU
attributes << "// no attributes";
}
std::stringstream setters;
std::stringstream methods;
if (uniformSize > 0 || attributeSize > 0) {
setters << "\n";
methods << "\n";
}
if (shaderStruct.out.layout.maxGeometryVertices > 0) {
methods << "\tint getMaxGeometryVertices() const {\n";
methods << "\t\treturn " << shaderStruct.out.layout.maxGeometryVertices << ";\n";
methods << "\t}\n\n;";
}
if (shaderStruct.out.layout.primitiveType != video::Primitive::Max) {
methods << "\tvideo::Primitive getPrimitiveTypeOut() const {\n";
methods << "\t\treturn video::Primitive::" << util::getPrimitiveTypeString(shaderStruct.out.layout.primitiveType) << ";\n";
methods << "\t}\n\n;";
}
if (shaderStruct.in.layout.primitiveType != video::Primitive::Max) {
methods << "\tvideo::Primitive getPrimitiveTypeIn() const {\n";
methods << "\t\treturn video::Primitive::" << util::getPrimitiveTypeString(shaderStruct.in.layout.primitiveType) << ";\n";
methods << "\t}\n\n;";
}
for (int i = 0; i < uniformSize; ++i) {
const Variable& v = shaderStruct.uniforms[i];
const bool isInteger = v.isSingleInteger();
const std::string& uniformName = util::convertName(v.name, true);
setters << "\tinline bool set" << uniformName << "(";
methods << "\tinline bool set" << uniformName << "(";
const Types& cType = util::resolveTypes(v.type);
auto layoutIter = shaderStruct.layouts.find(v.name);
Layout layout;
@ -110,126 +125,119 @@ bool generateSrc(const std::string& templateShader, const std::string& templateU
}
if (v.arraySize > 0 && isInteger) {
setters << "const ";
methods << "const ";
} else if (cType.passBy == PassBy::Reference) {
setters << "const ";
methods << "const ";
}
setters << cType.ctype;
methods << cType.ctype;
if (v.arraySize == -1 || cType.passBy == PassBy::Pointer) {
setters << "*";
methods << "*";
} else if (cType.passBy == PassBy::Reference) {
if (v.arraySize <= 0) {
setters << "&";
methods << "&";
}
} else if (cType.passBy == PassBy::Value) {
}
if (v.arraySize > 0) {
setters << " (&" << v.name << ")[" << v.arraySize << "]";
methods << " (&" << v.name << ")[" << v.arraySize << "]";
} else {
setters << " " << v.name;
methods << " " << v.name;
}
if (v.isSampler() && layout.binding != -1) {
setters << " = video::TextureUnit::" << convertToTexUnit(layout.binding);
methods << " = video::TextureUnit::" << convertToTexUnit(layout.binding);
}
if (v.arraySize == -1) {
setters << ", int amount";
methods << ", int amount";
}
setters << ") const {\n";
methods << ") const {\n";
setters << "\t\tconst int location = ";
methods << "\t\tconst int location = ";
if (layout.location != -1) {
setters << layout.location << ";\n";
methods << layout.location << ";\n";
} else {
setters << "getUniformLocation(\"" << v.name << "\");\n";
setters << "\t\tif (location == -1) {\n";
setters << "\t\t\treturn false;\n";
setters << "\t\t}\n";
methods << "getUniformLocation(\"" << v.name << "\");\n";
methods << "\t\tif (location == -1) {\n";
methods << "\t\t\treturn false;\n";
methods << "\t\t}\n";
}
setters << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize == -1 ? 2 : v.arraySize);
setters << "(location, " << v.name;
methods << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize == -1 ? 2 : v.arraySize);
methods << "(location, " << v.name;
if (v.arraySize > 0) {
setters << ", " << v.arraySize;
methods << ", " << v.arraySize;
} else if (v.arraySize == -1) {
setters << ", amount";
methods << ", amount";
}
setters << ");\n";
setters << "\t\treturn true;\n";
setters << "\t}\n";
methods << ");\n";
methods << "\t\treturn true;\n";
methods << "\t}\n";
if (v.isSampler()) {
if (layout.binding != -1) {
setters << "\n\tinline video::TextureUnit getBound" << uniformName << "TexUnit() const {\n";
setters << "\t\treturn video::TextureUnit::" << convertToTexUnit(layout.binding) << ";\n\t}\n";
methods << "\n\tinline video::TextureUnit getBound" << uniformName << "TexUnit() const {\n";
methods << "\t\treturn video::TextureUnit::" << convertToTexUnit(layout.binding) << ";\n\t}\n";
}
}
if (v.isSampler() || v.isImage()) {
if (layout.imageFormat != video::ImageFormat::Max) {
setters << "\n\tinline video::ImageFormat getImageFormat" << uniformName << "() const {\n";
setters << "\t\treturn video::ImageFormat::" << util::getImageFormatTypeString(layout.imageFormat) << ";\n\t}\n";
methods << "\n\tinline video::ImageFormat getImageFormat" << uniformName << "() const {\n";
methods << "\t\treturn video::ImageFormat::" << util::getImageFormatTypeString(layout.imageFormat) << ";\n\t}\n";
}
// TODO: generate texture with correct format and constraints.
}
if (layout.primitiveType != PrimitiveType::None) {
// TODO:
}
if (layout.blockLayout != BlockLayout::unknown) {
// TODO:
}
if (layout.localSize.x != -1) {
setters << "\n\tinline int getLocalSizeX() const {\n";
setters << "\t\treturn " << layout.localSize.x << ";\n\t}\n";
methods << "\n\tinline int getLocalSizeX() const {\n";
methods << "\t\treturn " << layout.localSize.x << ";\n\t}\n";
}
if (layout.localSize.y != -1) {
setters << "\n\tinline int getLocalSizeY() const {\n";
setters << "\t\treturn " << layout.localSize.y << ";\n\t}\n";
methods << "\n\tinline int getLocalSizeY() const {\n";
methods << "\t\treturn " << layout.localSize.y << ";\n\t}\n";
}
if (layout.localSize.z != -1) {
setters << "\n\tinline int getLocalSizeZ() const {\n";
setters << "\t\treturn " << layout.localSize.z << ";\n\t}\n";
methods << "\n\tinline int getLocalSizeZ() const {\n";
methods << "\t\treturn " << layout.localSize.z << ";\n\t}\n";
}
if (v.arraySize > 0) {
setters << "\n\tinline bool set" << uniformName << "(" << "const std::vector<" << cType.ctype << ">& var) const {\n";
setters << "\t\tconst int location = getUniformLocation(\"" << v.name;
setters << "\");\n\t\tif (location == -1) {\n";
setters << "\t\t\treturn false;\n";
setters << "\t\t}\n";
setters << "\t\tcore_assert((int)var.size() == " << v.arraySize << ");\n";
setters << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize) << "(location, &var.front(), var.size());\n";
setters << "\t\treturn true;\n";
setters << "\t}\n";
methods << "\n\tinline bool set" << uniformName << "(" << "const std::vector<" << cType.ctype << ">& var) const {\n";
methods << "\t\tconst int location = getUniformLocation(\"" << v.name;
methods << "\");\n\t\tif (location == -1) {\n";
methods << "\t\t\treturn false;\n";
methods << "\t\t}\n";
methods << "\t\tcore_assert((int)var.size() == " << v.arraySize << ");\n";
methods << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize) << "(location, &var.front(), var.size());\n";
methods << "\t\treturn true;\n";
methods << "\t}\n";
} else if (cType.type == Variable::Type::VEC2 || cType.type == Variable::Type::VEC3 || cType.type == Variable::Type::VEC4) {
setters << "\n\tinline bool set" << uniformName << "(" << "const std::vector<float>& var) const {\n";
setters << "\t\tconst int location = getUniformLocation(\"" << v.name;
setters << "\");\n\t\tif (location == -1) {\n";
setters << "\t\t\treturn false;\n";
setters << "\t\t}\n";
setters << "\t\tcore_assert(int(var.size()) % " << cType.components << " == 0);\n";
setters << "\t\tsetUniformfv(location, &var.front(), " << cType.components << ", " << cType.components << ");\n";
setters << "\t\treturn true;\n";
setters << "\t}\n";
methods << "\n\tinline bool set" << uniformName << "(" << "const std::vector<float>& var) const {\n";
methods << "\t\tconst int location = getUniformLocation(\"" << v.name;
methods << "\");\n\t\tif (location == -1) {\n";
methods << "\t\t\treturn false;\n";
methods << "\t\t}\n";
methods << "\t\tcore_assert(int(var.size()) % " << cType.components << " == 0);\n";
methods << "\t\tsetUniformfv(location, &var.front(), " << cType.components << ", " << cType.components << ");\n";
methods << "\t\treturn true;\n";
methods << "\t}\n";
}
if (i < uniformSize- - 2) {
setters << "\n";
methods << "\n";
}
#if 0
if (v.arraySize == -1 || v.arraySize > 1) {
setters << "\tinline bool set" << uniformName << "(";
methods << "\tinline bool set" << uniformName << "(";
const Types& cType = util::getTypes(v.type);
setters << "const std::vector<" << cType.ctype << ">& " << v.name << ") const {\n";
setters << "\t\tif (!hasUniform(\"" << v.name << "[0]\")) {\n";
setters << "\t\t\treturn false;\n";
setters << "\t\t}\n";
setters << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize == -1 ? 2 : v.arraySize);
setters << "(\"" << v.name << "[0]\", &" << v.name << "[0], " << v.name << ".size());\n";
setters << "\t\treturn true;\n";
setters << "\t}\n";
methods << "const std::vector<" << cType.ctype << ">& " << v.name << ") const {\n";
methods << "\t\tif (!hasUniform(\"" << v.name << "[0]\")) {\n";
methods << "\t\t\treturn false;\n";
methods << "\t\t}\n";
methods << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize == -1 ? 2 : v.arraySize);
methods << "(\"" << v.name << "[0]\", &" << v.name << "[0], " << v.name << ".size());\n";
methods << "\t\treturn true;\n";
methods << "\t}\n";
if (i < uniformSize- - 2) {
setters << "\n";
methods << "\n";
}
}
#endif
@ -238,70 +246,70 @@ bool generateSrc(const std::string& templateShader, const std::string& templateU
const Variable& v = shaderStruct.attributes[i];
const std::string& attributeName = util::convertName(v.name, true);
const bool isInt = v.isInteger();
setters << "\tinline bool init" << attributeName << "Custom(size_t stride = ";
setters << "sizeof(" << util::resolveTypes(v.type).ctype << ")";
setters << ", const void* pointer = nullptr, video::DataType type = ";
methods << "\tinline bool init" << attributeName << "Custom(size_t stride = ";
methods << "sizeof(" << util::resolveTypes(v.type).ctype << ")";
methods << ", const void* pointer = nullptr, video::DataType type = ";
if (isInt) {
setters << "video::DataType::Int";
methods << "video::DataType::Int";
} else {
setters << "video::DataType::Float";
methods << "video::DataType::Float";
}
setters << ", int size = ";
setters << util::resolveTypes(v.type).components << ", ";
setters << "bool isInt = ";
setters << (isInt ? "true" : "false");
setters << ", bool normalize = false) const {\n";
setters << "\t\tconst int loc = enableVertexAttributeArray(\"" << v.name << "\");\n";
setters << "\t\tif (loc == -1) {\n";
setters << "\t\t\treturn false;\n";
setters << "\t\t}\n";
setters << "\t\tif (isInt) {\n";
setters << "\t\t\tsetVertexAttributeInt(loc, size, type, stride, pointer);\n";
setters << "\t\t} else {\n";
setters << "\t\t\tsetVertexAttribute(loc, size, type, normalize, stride, pointer);\n";
setters << "\t\t}\n";
setters << "\t\treturn true;\n";
setters << "\t}\n\n";
setters << "\tinline int getLocation" << attributeName << "() const {\n";
setters << "\t\treturn getAttributeLocation(\"" << v.name << "\");\n";
setters << "\t}\n\n";
setters << "\tinline int getComponents" << attributeName << "() const {\n";
setters << "\t\treturn getAttributeComponents(\"" << v.name << "\");\n";
setters << "\t}\n\n";
setters << "\tinline bool init" << attributeName << "() const {\n";
setters << "\t\tconst int loc = enableVertexAttributeArray(\"" << v.name << "\");\n";
setters << "\t\tif (loc == -1) {\n";
setters << "\t\t\treturn false;\n";
setters << "\t\t}\n";
setters << "\t\tconst size_t stride = sizeof(" << util::resolveTypes(v.type).ctype << ");\n";
setters << "\t\tconst void* pointer = nullptr;\n";
setters << "\t\tconst video::DataType type = ";
methods << ", int size = ";
methods << util::resolveTypes(v.type).components << ", ";
methods << "bool isInt = ";
methods << (isInt ? "true" : "false");
methods << ", bool normalize = false) const {\n";
methods << "\t\tconst int loc = enableVertexAttributeArray(\"" << v.name << "\");\n";
methods << "\t\tif (loc == -1) {\n";
methods << "\t\t\treturn false;\n";
methods << "\t\t}\n";
methods << "\t\tif (isInt) {\n";
methods << "\t\t\tsetVertexAttributeInt(loc, size, type, stride, pointer);\n";
methods << "\t\t} else {\n";
methods << "\t\t\tsetVertexAttribute(loc, size, type, normalize, stride, pointer);\n";
methods << "\t\t}\n";
methods << "\t\treturn true;\n";
methods << "\t}\n\n";
methods << "\tinline int getLocation" << attributeName << "() const {\n";
methods << "\t\treturn getAttributeLocation(\"" << v.name << "\");\n";
methods << "\t}\n\n";
methods << "\tinline int getComponents" << attributeName << "() const {\n";
methods << "\t\treturn getAttributeComponents(\"" << v.name << "\");\n";
methods << "\t}\n\n";
methods << "\tinline bool init" << attributeName << "() const {\n";
methods << "\t\tconst int loc = enableVertexAttributeArray(\"" << v.name << "\");\n";
methods << "\t\tif (loc == -1) {\n";
methods << "\t\t\treturn false;\n";
methods << "\t\t}\n";
methods << "\t\tconst size_t stride = sizeof(" << util::resolveTypes(v.type).ctype << ");\n";
methods << "\t\tconst void* pointer = nullptr;\n";
methods << "\t\tconst video::DataType type = ";
if (isInt) {
setters << "video::DataType::Int";
methods << "video::DataType::Int";
} else {
setters << "video::DataType::Float";
methods << "video::DataType::Float";
}
setters << ";\n";
setters << "\t\tconst int size = getAttributeComponents(loc);\n";
methods << ";\n";
methods << "\t\tconst int size = getAttributeComponents(loc);\n";
if (isInt) {
setters << "\t\tsetVertexAttributeInt(loc, size, type, stride, pointer);\n";
methods << "\t\tsetVertexAttributeInt(loc, size, type, stride, pointer);\n";
} else {
setters << "\t\tsetVertexAttribute(loc, size, type, false, stride, pointer);\n";
methods << "\t\tsetVertexAttribute(loc, size, type, false, stride, pointer);\n";
}
setters << "\t\treturn true;\n";
setters << "\t}\n\n";
setters << "\tinline bool set" << attributeName << "Divisor(uint32_t divisor) const {\n";
setters << "\t\tconst int location = getAttributeLocation(\"" << v.name << "\");\n";
setters << "\t\treturn setDivisor(location, divisor);\n";
setters << "\t}\n";
methods << "\t\treturn true;\n";
methods << "\t}\n\n";
methods << "\tinline bool set" << attributeName << "Divisor(uint32_t divisor) const {\n";
methods << "\t\tconst int location = getAttributeLocation(\"" << v.name << "\");\n";
methods << "\t\treturn setDivisor(location, divisor);\n";
methods << "\t}\n";
if (i < attributeSize - 1) {
setters << "\n";
methods << "\n";
}
}
if (!shaderStruct.uniformBlocks.empty()) {
setters << "\n";
methods << "\n";
}
std::stringstream ub;
std::stringstream shutdown;
@ -354,17 +362,17 @@ bool generateSrc(const std::string& templateShader, const std::string& templateU
ub << "\n\tinline operator const video::UniformBuffer&() const {\n";
ub << "\t\treturn _" << uniformBufferName << ";\n";
ub << "\t}\n";
setters << "\t/**\n";
setters << "\t * @brief The the uniform buffer for the uniform block " << ubuf.name << "\n";
setters << "\t */\n";
setters << "\tinline bool set" << uniformBufferStructName << "(const video::UniformBuffer& buf) {\n";
setters << "\t\treturn setUniformBuffer(\"" << ubuf.name << "\", buf);\n";
setters << "\t}\n";
methods << "\t/**\n";
methods << "\t * @brief The the uniform buffer for the uniform block " << ubuf.name << "\n";
methods << "\t */\n";
methods << "\tinline bool set" << uniformBufferStructName << "(const video::UniformBuffer& buf) {\n";
methods << "\t\treturn setUniformBuffer(\"" << ubuf.name << "\", buf);\n";
methods << "\t}\n";
std::string generatedUb = core::string::replaceAll(templateUniformBuffer, "$name$", uniformBufferStructName);
generatedUb = core::string::replaceAll(generatedUb, "$namespace$", namespaceSrc);
generatedUb = core::string::replaceAll(generatedUb, "$uniformbuffers$", ub.str());
generatedUb = core::string::replaceAll(generatedUb, "$setters$", "");
generatedUb = core::string::replaceAll(generatedUb, "$methods$", "");
generatedUb = core::string::replaceAll(generatedUb, "$shutdown$", shutdown.str());
const std::string targetFileUb = sourceDirectory + uniformBufferStructName + ".h";
@ -379,10 +387,10 @@ bool generateSrc(const std::string& templateShader, const std::string& templateU
}
src = core::string::replaceAll(src, "$attributes$", attributes.str());
src = core::string::replaceAll(src, "$setters$", setters.str());
src = core::string::replaceAll(src, "$methods$", methods.str());
src = core::string::replaceAll(src, "$includes$", includes.str());
const std::string targetFile = sourceDirectory + filename + ".h";
const std::string targetFile = sourceDirectory + filename + ".h" + postfix;
Log::debug("Generate shader bindings for %s at %s", shaderStruct.name.c_str(), targetFile.c_str());
if (!filesystem->syswrite(targetFile, src)) {
Log::error("Failed to write %s", targetFile.c_str());

View File

@ -11,6 +11,6 @@
namespace shadertool {
extern bool generateSrc(const std::string& templateShader, const std::string& templateUniformBuffer, const ShaderStruct& shaderStruct,
const io::FilesystemPtr& filesystem, const std::string& namespaceSrc, const std::string& sourceDirectory, const std::string& shaderDirectory);
const io::FilesystemPtr& filesystem, const std::string& namespaceSrc, const std::string& sourceDirectory, const std::string& shaderDirectory, const std::string& postfix);
}

View File

@ -17,8 +17,7 @@
namespace shadertool {
static const char* PrimitiveTypeStr[] {
nullptr,
static const char* PrimitiveStr[] {
"points",
"lines",
"lines_adjacency",
@ -27,18 +26,15 @@ static const char* PrimitiveTypeStr[] {
"line_strip",
"triangle_strip"
};
static_assert(lengthof(PrimitiveTypeStr) == std::enum_value(PrimitiveType::Max), "PrimitiveTypeStr doesn't match enum");
static_assert(lengthof(PrimitiveStr) == std::enum_value(video::Primitive::Max), "PrimitiveStr doesn't match enum");
static PrimitiveType layoutPrimitiveType(const std::string& token) {
for (int i = 0; i < lengthof(PrimitiveTypeStr); ++i) {
if (PrimitiveTypeStr[i] == nullptr) {
continue;
}
if (token == PrimitiveTypeStr[i]) {
return (PrimitiveType)i;
static video::Primitive layoutPrimitiveType(const std::string& token) {
for (int i = 0; i < lengthof(PrimitiveStr); ++i) {
if (token == PrimitiveStr[i]) {
return (video::Primitive)i;
}
}
return PrimitiveType::None;
return video::Primitive::Max;
}
bool parseLayout(TokenIterator& tok, Layout& layout) {
@ -156,7 +152,12 @@ bool parseLayout(TokenIterator& tok, Layout& layout) {
if (format != video::ImageFormat::Max) {
layout.imageFormat = format;
} else {
Log::warn("Unknown token given for layout: %s (line %i)", token.c_str(), tok.line());
video::Primitive primitiveType = layoutPrimitiveType(token);
if (primitiveType != video::Primitive::Max) {
layout.primitiveType = primitiveType;
} else {
Log::warn("Unknown token given for layout: %s (line %i)", token.c_str(), tok.line());
}
}
}
} while (token != ")");
@ -216,6 +217,10 @@ bool parse(ShaderStruct& shaderStruct, const std::string& shaderFile, const std:
Log::warn("SSBO not supported");
} else if (token == "uniform") {
v = &shaderStruct.uniforms;
} else if (hasLayout && token == "in") {
shaderStruct.in.layout = layout;
} else if (hasLayout && token == "out") {
shaderStruct.out.layout = layout;
} else if (uniformBlock) {
if (token == "}") {
uniformBlock = false;

View File

@ -62,7 +62,7 @@ $uniformarrayinfo$
}
}
$setters$
$methods$
};
typedef std::shared_ptr<$name$> $name$Ptr;

View File

@ -95,6 +95,7 @@ core::AppState ShaderTool::onRunning() {
_shaderDirectory = getArgVal("--shaderdir");
_sourceDirectory = getArgVal("--sourcedir",
_filesystem->basePath() + "src/modules/" + _namespaceSrc + "/");
_postfix = getArgVal("--postfix", "");
if (!core::string::endsWith(_shaderDirectory, "/")) {
_shaderDirectory = _shaderDirectory + "/";
@ -138,7 +139,7 @@ core::AppState ShaderTool::onRunning() {
}
if (!shadertool::generateSrc(templateShader, templateUniformBuffer, _shaderStruct,
filesystem(), _namespaceSrc, _sourceDirectory, _shaderDirectory)) {
filesystem(), _namespaceSrc, _sourceDirectory, _shaderDirectory, _postfix)) {
Log::error("Failed to generate shader source for %s", _shaderfile.c_str());
_exitCode = 1;
return core::AppState::Cleanup;
@ -199,7 +200,7 @@ core::AppState ShaderTool::onRunning() {
}
if (!shadertool::generateSrc(templateShader, templateUniformBuffer, _shaderStruct,
filesystem(), _namespaceSrc, _sourceDirectory, _shaderDirectory)) {
filesystem(), _namespaceSrc, _sourceDirectory, _shaderDirectory, _postfix)) {
Log::error("Failed to generate shader source for %s", _shaderfile.c_str());
_exitCode = 1;
return core::AppState::Cleanup;

View File

@ -19,6 +19,7 @@ protected:
ShaderStruct _shaderStruct;
std::string _namespaceSrc;
std::string _sourceDirectory;
std::string _postfix;
std::string _shaderDirectory;
std::string _shaderTemplateFile;
std::string _glslangValidatorBin;

View File

@ -23,18 +23,6 @@ enum class BlockLayout {
std430
};
enum class PrimitiveType {
None,
Points,
Lines,
LinesAdjacency,
Triangles,
TrianglesAdjacency,
LineStrip,
TriangleStrip,
Max
};
struct Variable {
enum Type {
DOUBLE = 0, FLOAT, UNSIGNED_INT, INT, BOOL,
@ -93,7 +81,7 @@ struct Layout {
bool pixelCenterInteger = false; // 4.0
bool earlyFragmentTests = false; // 4.2
glm::ivec3 localSize { -1 };
PrimitiveType primitiveType = PrimitiveType::None;
video::Primitive primitiveType = video::Primitive::Max;
BlockLayout blockLayout = BlockLayout::unknown;
video::ImageFormat imageFormat = video::ImageFormat::Max;
@ -110,12 +98,21 @@ struct ImageFormatType {
const char* ctype;
};
struct PrimitiveType {
video::Primitive type;
const char* str;
};
struct UniformBlock {
std::string name;
std::vector<Variable> members;
Layout layout;
};
struct InOut {
Layout layout;
};
struct ShaderStruct {
std::string name;
std::string filename;
@ -129,4 +126,6 @@ struct ShaderStruct {
std::vector<Variable> varyings;
// fragment only
std::vector<Variable> outs;
InOut in;
InOut out;
};

View File

@ -21,7 +21,7 @@ $uniformbuffers$
void shutdown() {
$shutdown$
}
$setters$
$methods$
};
};

View File

@ -143,6 +143,29 @@ const char* getImageFormatTypeString(video::ImageFormat format) {
return nullptr;
}
#define PRIMITVEENTRY(x) {video::Primitive::x, #x}
static const PrimitiveType cPrimitiveType[] = {
PRIMITVEENTRY(Points),
PRIMITVEENTRY(Lines),
PRIMITVEENTRY(LinesAdjacency),
PRIMITVEENTRY(Triangles),
PRIMITVEENTRY(TrianglesAdjacency),
PRIMITVEENTRY(LineStrip),
PRIMITVEENTRY(TriangleStrip)
};
#undef PRIMITVEENTRY
static_assert((size_t)video::Primitive::Max == lengthof(cPrimitiveType), "mismatch in primitive types");
const char* getPrimitiveTypeString(video::Primitive primitive) {
const int max = std::enum_value(video::Primitive::Max);
for (int i = 0; i < max; ++i) {
if (primitive == cPrimitiveType[i].type) {
return cPrimitiveType[i].str;
}
}
return nullptr;
}
std::string uniformSetterPostfix(const Variable::Type type, int amount) {
switch (type) {
case Variable::MAX:

View File

@ -30,6 +30,8 @@ extern video::ImageFormat getImageFormat(const std::string& type, int line);
extern const char* getImageFormatGLType(video::ImageFormat format);
extern const char* getImageFormatTypeString(video::ImageFormat format);
extern const char* getPrimitiveTypeString(video::Primitive primitive);
extern int getComponents(const Variable::Type type);
extern Variable::Type getType(const std::string& type, int line);