#include "device/dvc_buffer_accessor.h" #include "math/dvc_vector2.h" #include "math/dvc_vector3.h" #include "math/dvc_matrix4.h" #include "pipe/dvc_render_pipe.h" #include "device/dvc_uniform_buffer.h" template StandardVertexShader::StandardVertexShader() { m_outputVertexDesc.addElement("v_position", davinci::VET_POSITION, davinci::CT_Float32, davinci::DT_Vec3); if constexpr(WithNormal) m_outputVertexDesc.addElement("v_normal", davinci::VET_NORMAL, davinci::CT_Float32, davinci::DT_Vec3); if constexpr(WithUV) m_outputVertexDesc.addElement("v_uv", davinci::VET_TEXCOORD_0, davinci::CT_Float32, davinci::DT_Vec2); } template StandardVertexShader::~StandardVertexShader() { } template struct CompileTimeString { std::array data{}; std::size_t size = 0; constexpr void append(const char* str, std::size_t len) { for (std::size_t i = 0; i < len; ++i) { data[size++] = str[i]; } } constexpr void append(const char* str) { while (*str) { data[size++] = *str++; } } constexpr const char* c_str() const { return data.data(); } constexpr std::string_view view() const { return {data.data(), size}; } }; template constexpr auto buildNameString() { constexpr const char* prefix = "standard"; constexpr const char* normalString = WithNormal ? "+normal" : "-normal"; constexpr const char* uvString = WithUV ? "+uv" : "-uv"; constexpr std::size_t total_len = std::char_traits::length(prefix) + std::char_traits::length(normalString) + std::char_traits::length(uvString); CompileTimeString result; result.append(prefix); result.append(normalString); result.append(uvString); result.append(""); // null terminator return result; } template const char* StandardVertexShader::getName(void) const { static constexpr auto strName = buildNameString(); const char* p = strName.c_str(); return p; } template const davinci::VertexDesc& StandardVertexShader::getOutputVertexDesc() const { return m_outputVertexDesc; } template size_t StandardVertexShader::getOutputVertexByteSize(void) const { return m_outputVertexDesc.vertexByteSize(); } template void StandardVertexShader::prepare(const davinci::RenderPipe* pipe, SetInputAttributeFunc setInputAttributeFunc) { m_pipe = pipe; std::get(m_inputAccessors) = setInputAttributeFunc(davinci::VET_POSITION); if constexpr(WithNormal) std::get(m_inputAccessors) = setInputAttributeFunc(davinci::VET_NORMAL); if constexpr(WithUV) std::get(m_inputAccessors) = setInputAttributeFunc(davinci::VET_TEXCOORD_0); } /* template davinci::DeviceBufferAccessorConstPtr& StandardVertexShader::getPositionAccessor() { return std::get<0>(m_inputAccessors); } template davinci::DeviceBufferAccessorConstPtr& StandardVertexShader::getNormalAccessor() { if constexpr(WithNormal) return std::get<1>(m_inputAccessors); else return nullptr; } template davinci::DeviceBufferAccessorConstPtr& StandardVertexShader::getUVAccessor() { if constexpr(WithUV) return std::get(m_inputAccessors); else return nullptr; } */ template void StandardVertexShader::process(size_t index, void* outputVertex, davinci::fVector3& vertexWorldPos) { static const float DEFAULT_POSITION[] = {0.f, 0.f, 0.f}; static const float32_t DEFAULT_NORMAL[] = { 0.f, 0.f, 0.f }; static const float32_t DEFAULT_TEXCOORD0[] = { 0.f, 0.f}; const davinci::UniformBuffer& uniformBuffer = m_pipe->getUniformBuffer(); davinci::DeviceBufferAccessorConstPtr inputPosition = std::get<0>(m_inputAccessors); davinci::DeviceBufferAccessorConstPtr inputNormal = nullptr; if constexpr(WithNormal) inputNormal = std::get(m_inputAccessors); davinci::DeviceBufferAccessorConstPtr inputUV = nullptr; if constexpr(WithUV) inputUV = std::get(m_inputAccessors); davinci::fVector3 a_position(inputPosition ? (const float32_t*)(inputPosition->getElement(index)) : DEFAULT_POSITION); davinci::fVector3 a_normal(inputNormal ? (const float32_t*)(inputNormal->getElement(index)) : DEFAULT_NORMAL); davinci::fVector2 a_uv(inputUV ? (const float32_t*)(inputUV->getElement(index)) : DEFAULT_TEXCOORD0); davinci::fMatrix4 mat_world = davinci::fMatrix4::IDENTITY; if (davinci::fMatrix4* p_mat_world = (davinci::fMatrix4*)(uniformBuffer.getAttribute("self:world_transform"))) { mat_world = *p_mat_world; } davinci::fMatrix4 mat_camera_view_proj = davinci::fMatrix4::IDENTITY; if (davinci::fMatrix4* p_mat_camera_view_proj = (davinci::fMatrix4*)(uniformBuffer.getAttribute("camera:view_proj_mat"))) { mat_camera_view_proj = *p_mat_camera_view_proj; } vertexWorldPos = mat_world * a_position; davinci::fVector3 v_position = mat_camera_view_proj * vertexWorldPos; int32_t outputOffset=0; memcpy((char*)outputVertex + m_outputVertexDesc.getElement(outputOffset++)->offset, &v_position, sizeof(davinci::fVector3)); if constexpr(WithNormal) { davinci::fMatrix4 matNormal = davinci::fMatrix4::IDENTITY; if (davinci::fMatrix4* p_mat_normal = (davinci::fMatrix4*)(uniformBuffer.getAttribute("self:world_transform_inverse_trans"))) { matNormal = *p_mat_normal; } davinci::fVector3 v_normal = (matNormal * davinci::fVector4(a_normal, 0)).xyz().normalise(); memcpy((char*)outputVertex + m_outputVertexDesc.getElement(outputOffset++)->offset, &v_normal, sizeof(davinci::fVector3)); } if constexpr(WithUV) { memcpy((char*)outputVertex + m_outputVertexDesc.getElement(outputOffset++)->offset, &a_uv, sizeof(float32_t) * 2); } }