diff --git a/src/game/Global.cpp b/src/game/Global.cpp index 9476d58..5db304d 100644 --- a/src/game/Global.cpp +++ b/src/game/Global.cpp @@ -1,6 +1,5 @@ #include "Global.h" #include "bx/bx.h" -#include "bx/float4x4_t.h" #include "bx/math.h" #include diff --git a/src/game/Level.cpp b/src/game/Level.cpp index a34e60e..e19d85b 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -1,8 +1,11 @@ #include "Global.h" +#include "Input.h" #include "Instance.h" #include "Level.h" #include "Log.h" +#include "bgfx/bgfx.h" #include +#include namespace { @@ -10,10 +13,34 @@ namespace namespace Game { + void EntityRenderData::Render(const Model* models, const Material* materials) + { + if (ModelHandle == UINT16_MAX || MaterialHandle == UINT16_MAX) return; + + Transform.UpdateMatrix(); + bgfx::setTransform(Transform.M.M); + + const Model& currentModel = models[ModelHandle]; + const Material& currentMaterial = materials[MaterialHandle]; + bgfx::setVertexBuffer(0, currentModel.VertexBuffer); + bgfx::setIndexBuffer(currentModel.IndexBuffer); + bgfx::setState(currentMaterial.State); + + float TimeValues[4]{0.0f}; + TimeValues[0] = GetInstance().Now; + bgfx::setUniform(currentMaterial.Uniforms[Material::UTime], TimeValues); + bgfx::setUniform(currentMaterial.Uniforms[Material::UDotColor], TestColor); + + bgfx::submit(0, currentMaterial.Shader); + } + void Level::Setup(GameData& data) { Log("Level setup"); - Cubes.Setup(data.EntityStorage); + void* storagePtr = data.EntityStorage; + bool needReset = false; + needReset |= Cubes.Setup(storagePtr, needReset); + needReset |= Tests.Setup(storagePtr, needReset); if (Cubes.Count == 0) { for (uint32_t yy = 0; yy < 11; ++yy) @@ -31,15 +58,29 @@ namespace Game Cube* floor = Cubes.New(); } + if (Tests.Count == 0) + { + Tests.New(); + } } void Level::Update() { + if (GetKey(ScanCode::R)) + { + Cubes.Count = 0; + Tests.Count = 0; + Setup(GetShared().Game); + } + Cubes.Update(); + Tests.Update(); } void Cube::Setup() { + EData.MaterialHandle = 0; + EData.ModelHandle = 0; } void Cube::Update() @@ -48,26 +89,32 @@ namespace Game { double globalTime = GetInstance().Now; double time = TestY <= 5 ? globalTime * 1.0f : 0.0f; - if (TestX == 4 && TestY == 4) - { - // bx::mtxTranslate(Transform.M, 0, 0, bx::lerp(-20.0f, -32.0f, bx::sin(globalTime* 0.5f) * 0.5 + 0.5)); - // bx::mtxTranslate(Transform.M, 0, 0, bx::lerp(0.0f, -32.0f, bx::sin(globalTime* 0.5f) * 0.5 + 0.5)); - } - else - { - float scale = 1.0f + TestX * 0.4f; - Transform::CreateTransform( - Transform.M.M, - bx::Vec3{TestX * 10.0f - 40.0f, TestY * 10.0f - 40.0f, (float)TestX}, - bx::fromEuler( - {static_cast(time * 10.0f + TestX), static_cast(time * 5.0f * TestY), 0.0f}), - {scale, scale, scale}); - } + float scale = 1.0f + TestX * 0.4f; + EData.Transform.Position = bx::Vec3{TestX * 2.0f, TestY * 2.0f, 0.0f}; + EData.Transform.Scale = {scale, scale, scale}; } else { - Transform::CreateTransform( - Transform.M.M, {0.0f, -30.0f, 100.0f}, bx::Quaternion(0.0f, 0.0f, 0.0f, 1.0f), {100.0f, 10.0f, 100.0f}); + EData.Transform.Position = {0.0f, -1.0f, 0.0f}; + EData.Transform.Scale = {100.0f, 1.0f, 100.0f}; + EData.TestColor[0] = 0.3f; + EData.TestColor[1] = 0.4f; + EData.TestColor[2] = 0.8f; } } + + void TestEntity::Setup() + { + EData.MaterialHandle = 0; + EData.ModelHandle = 1; + + EData.Transform.Position = {0.0f, 0.0f, 10.0f}; + } + + void TestEntity::Update() + { + EData.TestColor[0] = 0.6f; + EData.TestColor[1] = 0.9f; + EData.TestColor[2] = 0.5f; + } } // namespace Game diff --git a/src/game/Level.h b/src/game/Level.h index b2495a2..b3a62a4 100644 --- a/src/game/Level.h +++ b/src/game/Level.h @@ -2,20 +2,35 @@ #include "../engine/Shared.h" #include "Global.h" #include "Log.h" +#include "rendering/Rendering.h" #include +#include namespace Game { + struct EntityRenderData + { + float TestColor[4]{1.0f, 1.0f, 1.0f, 1.0f}; + Transform Transform; + uint16_t MaterialHandle = UINT16_MAX; + uint16_t ModelHandle = UINT16_MAX; - typedef uint16_t CubeHandle; + void Render(const Model* models, const Material* materials); + }; struct Cube { int32_t TestX = -1; int32_t TestY = -1; - Transform Transform; - uint16_t MaterialIdx = 0; - uint16_t ModelIdx = 0; + EntityRenderData EData; + + void Setup(); + void Update(); + }; + + struct TestEntity + { + EntityRenderData EData; void Setup(); void Update(); @@ -29,15 +44,19 @@ namespace Game uint32_t EntitySize = 0; public: - uint64_t Setup(void* ptr) + // Returns true if size changed + bool Setup(void*& ptr, bool forceReset) { - if (EntitySize != sizeof(T)) + bool changed = false; + if (EntitySize != sizeof(T) || forceReset) { Count = 0; + changed = true; } EntitySize = sizeof(T); Data = reinterpret_cast(ptr); - return C * sizeof(T); + ptr = (uint8_t*)ptr + (C * EntitySize); + return changed; } T* New() @@ -76,12 +95,22 @@ namespace Game Data[i].Update(); } } + + void Render(const Model* models, const Material* materials) + { + for (int32_t i = 0; i < Count; ++i) + { + T* c = Get(i); + if (c) c->EData.Render(models, materials); + } + } }; class Level { public: EntityManager Cubes; + EntityManager Tests; public: void Setup(GameData& data); diff --git a/src/game/Mesh.cpp b/src/game/Mesh.cpp index a3aba65..56357ff 100644 --- a/src/game/Mesh.cpp +++ b/src/game/Mesh.cpp @@ -1,5 +1,6 @@ #include "Log.h" #include "Mesh.h" +#include "bx/bx.h" #define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION @@ -8,10 +9,11 @@ namespace Game { - void LoadMesh(Model& mesh) + void LoadMesh(Model& mesh, const char* path) { mesh.VertLayout.begin() .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float) .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true) .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float) .end(); @@ -20,11 +22,15 @@ namespace Game tinygltf::TinyGLTF loader; std::string warn; std::string err; - bool loadSuccess = loader.LoadASCIIFromFile(&model, &err, &warn, "models/cube.gltf"); + bool loadSuccess = loader.LoadASCIIFromFile(&model, &err, &warn, path); if (!warn.empty()) Log("WARN: %s", warn.c_str()); if (!err.empty()) Log("ERR: %s", err.c_str()); - if (!loadSuccess) Log("Model load failed!"); + if (!loadSuccess) + { + Log("Model load failed!"); + return; + } tinygltf::Primitive primitive = model.meshes[0].primitives[0]; { @@ -37,12 +43,16 @@ namespace Game } { tinygltf::Accessor posAccessor = model.accessors.at(primitive.attributes.at("POSITION")); + tinygltf::Accessor normalAccessor = model.accessors.at(primitive.attributes.at("NORMAL")); tinygltf::Accessor uvAccessor = model.accessors.at(primitive.attributes.at("TEXCOORD_0")); tinygltf::BufferView posBufferView = model.bufferViews[posAccessor.bufferView]; + tinygltf::BufferView normalBufferView = model.bufferViews[normalAccessor.bufferView]; tinygltf::BufferView uvBufferView = model.bufferViews[uvAccessor.bufferView]; int posStride = posAccessor.ByteStride(posBufferView); + int normalStride = normalAccessor.ByteStride(normalBufferView); int uvStride = uvAccessor.ByteStride(uvBufferView); tinygltf::Buffer posBuffer = model.buffers[posBufferView.buffer]; + tinygltf::Buffer normalBuffer = model.buffers[normalBufferView.buffer]; tinygltf::Buffer uvBuffer = model.buffers[uvBufferView.buffer]; uint32_t vertexCount = posBufferView.byteLength / posStride; @@ -52,6 +62,8 @@ namespace Game { PosColorVertex& v = *reinterpret_cast(vbMem->data + i * sizeof(PosColorVertex)); bx::memCopy(&v.x, &posBuffer.data.at(posBufferView.byteOffset + i * posStride), posStride); + bx::memCopy( + &v.n_x, &normalBuffer.data.at(normalBufferView.byteOffset + i * normalStride), normalStride); v.abgr = 0; bx::memCopy(&v.uv_x, &uvBuffer.data.at(uvBufferView.byteOffset + i * uvStride), uvStride); } diff --git a/src/game/Mesh.h b/src/game/Mesh.h index a339b9d..a7272e8 100644 --- a/src/game/Mesh.h +++ b/src/game/Mesh.h @@ -4,5 +4,5 @@ namespace Game { - void LoadMesh(Model& mesh); + void LoadMesh(Model& mesh, const char* path); } diff --git a/src/game/compiled-shaders/dx11/frag.bin b/src/game/compiled-shaders/dx11/frag.bin index 627c200..8fb21c4 100644 Binary files a/src/game/compiled-shaders/dx11/frag.bin and b/src/game/compiled-shaders/dx11/frag.bin differ diff --git a/src/game/compiled-shaders/dx11/vert.bin b/src/game/compiled-shaders/dx11/vert.bin index 7898a40..f71e19f 100644 Binary files a/src/game/compiled-shaders/dx11/vert.bin and b/src/game/compiled-shaders/dx11/vert.bin differ diff --git a/src/game/compiled-shaders/glsl/frag.bin b/src/game/compiled-shaders/glsl/frag.bin index 48b43e2..4c7502c 100644 Binary files a/src/game/compiled-shaders/glsl/frag.bin and b/src/game/compiled-shaders/glsl/frag.bin differ diff --git a/src/game/compiled-shaders/glsl/vert.bin b/src/game/compiled-shaders/glsl/vert.bin index 72079f3..53d0194 100644 Binary files a/src/game/compiled-shaders/glsl/vert.bin and b/src/game/compiled-shaders/glsl/vert.bin differ diff --git a/src/game/compiled-shaders/spirv/frag.bin b/src/game/compiled-shaders/spirv/frag.bin index 6f7c44f..f8ee115 100644 Binary files a/src/game/compiled-shaders/spirv/frag.bin and b/src/game/compiled-shaders/spirv/frag.bin differ diff --git a/src/game/compiled-shaders/spirv/vert.bin b/src/game/compiled-shaders/spirv/vert.bin index 3811303..763d620 100644 Binary files a/src/game/compiled-shaders/spirv/vert.bin and b/src/game/compiled-shaders/spirv/vert.bin differ diff --git a/src/game/rendering/Rendering.cpp b/src/game/rendering/Rendering.cpp index 67dfbbd..82c8c4d 100644 --- a/src/game/rendering/Rendering.cpp +++ b/src/game/rendering/Rendering.cpp @@ -129,15 +129,10 @@ namespace Game bgfx::setDebug(BGFX_DEBUG_TEXT); bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x303030ff, 1.0f, 0); - LoadMesh(Models[0]); + LoadMesh(Models[0], "models/cube.gltf"); + LoadMesh(Models[1], "models/zurg.gltf"); - bgfx::ShaderHandle vertexShader = loadShader("vert"); - bgfx::ShaderHandle fragmentShader = loadShader("frag"); - - Materials[0].Shader = bgfx::createProgram(vertexShader, fragmentShader, true); - Materials[0].State = 0 | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_WRITE_Z | - BGFX_STATE_DEPTH_TEST_LESS | BGFX_STATE_CULL_CCW | BGFX_STATE_MSAA; - Materials[0].Uniforms[Material::UniformTimeIdx] = bgfx::createUniform("u_time", bgfx::UniformType::Vec4); + Materials[0] = Material::LoadFromShader("vert", "frag"); if (!GetInstance().IsInitialized) { @@ -156,7 +151,7 @@ namespace Game shared.Dev.ChangedShaderCount = 0; // TODO: when to destroy shader? - // bgfx::destroy(Shader); + // TODO: only reload changed shaders bgfx::ShaderHandle vertexShader = loadShader("vert"); bgfx::ShaderHandle fragmentShader = loadShader("frag"); if (isValid(vertexShader) && isValid(fragmentShader)) @@ -178,7 +173,7 @@ namespace Game float delta = GetInstance().Delta; constexpr float moveSpeed = 10.0f; - constexpr float rotSpeed = 1.0f; + constexpr float rotSpeed = 0.6f; float forwardInput = (GetKey(ScanCode::W) ? 1.0f : 0.0f) + (GetKey(ScanCode::S) ? -1.0f : 0.0f); float rightInput = (GetKey(ScanCode::D) ? 1.0f : 0.0f) + (GetKey(ScanCode::A) ? -1.0f : 0.0f); @@ -189,14 +184,15 @@ namespace Game bx::Vec3 camForward = Cam.Transform.Forward(); bx::Vec3 camRight = Cam.Transform.Right(); - bx::Vec3 rotInput = {shared.Window.MouseDeltaY * delta, shared.Window.MouseDeltaX * delta, 0.0f}; + bx::Vec3 rotInput = { + shared.Window.MouseDeltaY * delta * rotSpeed, shared.Window.MouseDeltaX * delta * rotSpeed, 0.0f}; Cam.FreelookXRot += rotInput.x; Cam.FreelookYRot += rotInput.y; bx::mtxRotateY(Cam.Transform.Rotation.M, Cam.FreelookYRot); Cam.Transform.RotateLocal({Cam.FreelookXRot, 0.0f, 0.0f}); - Cam.Transform.TranslateLocal({0.0f, 0.0f, -forwardInput}); - Cam.Transform.TranslateLocal({-rightInput, 0.0f, 0.0f}); + Cam.Transform.TranslateLocal({0.0f, 0.0f, -inputVec.z}); + Cam.Transform.TranslateLocal({-inputVec.x, 0.0f, 0.0f}); bgfx::dbgTextPrintf(1, 4, 0x0f, "Cam forward: %.2f %.2f %.2f", camForward.x, camForward.y, camForward.z); } @@ -216,27 +212,8 @@ namespace Game bgfx::setViewRect(0, 0, 0, shared.Window.WindowWidth, shared.Window.WindowHeight); } - float TimeValues[4]{0.0f}; - TimeValues[0] = GetInstance().Now; - - for (int32_t i = 0; i < GetInstance().GameLevel.Cubes.Count; ++i) - { - Cube* c = GetInstance().GameLevel.Cubes.Get(i); - if (c) - { - bgfx::setTransform(c->Transform.M.M); - - Model& currentModel = Models[c->ModelIdx]; - Material& currentMaterial = Materials[c->MaterialIdx]; - bgfx::setVertexBuffer(0, currentModel.VertexBuffer); - bgfx::setIndexBuffer(currentModel.IndexBuffer); - bgfx::setState(currentMaterial.State); - bgfx::setUniform(Materials[0].Uniforms[Material::UniformTimeIdx], TimeValues); - - // Submit primitive for rendering to view 0. - bgfx::submit(0, currentMaterial.Shader); - } - } + GetInstance().GameLevel.Cubes.Render(Models, Materials); + GetInstance().GameLevel.Tests.Render(Models, Materials); bgfx::dbgTextPrintf(1, 1, 0x0F, "Time: %.1f", GetInstance().Now); bgfx::dbgTextPrintf(1, 2, 0x0F, "Frame: %u", GetInstance().FrameCounter); @@ -249,4 +226,18 @@ namespace Game { bgfx::shutdown(); } + + Material Material::LoadFromShader(const char* vertPath, const char* fragPath) + { + bgfx::ShaderHandle vertexShader = loadShader("vert"); + bgfx::ShaderHandle fragmentShader = loadShader("frag"); + + Material mat; + mat.Shader = bgfx::createProgram(vertexShader, fragmentShader, true); + mat.State = 0 | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_WRITE_Z | BGFX_STATE_DEPTH_TEST_LESS | + BGFX_STATE_CULL_CCW | BGFX_STATE_MSAA; + mat.Uniforms[Material::UTime] = bgfx::createUniform("u_time", bgfx::UniformType::Vec4); + mat.Uniforms[Material::UDotColor] = bgfx::createUniform("u_testColor", bgfx::UniformType::Vec4); + return mat; + } } // namespace Game diff --git a/src/game/rendering/Rendering.h b/src/game/rendering/Rendering.h index 9090fc1..faf3e48 100644 --- a/src/game/rendering/Rendering.h +++ b/src/game/rendering/Rendering.h @@ -11,6 +11,9 @@ namespace Game float x; float y; float z; + float n_x; + float n_y; + float n_z; uint32_t abgr; float uv_x; float uv_y; @@ -105,10 +108,16 @@ namespace Game struct Material { - static constexpr uint32_t UniformTimeIdx = 0; + enum UniformNames : uint32_t + { + UTime = 0, + UDotColor = 1, + }; + bgfx::ProgramHandle Shader; bgfx::UniformHandle Uniforms[8]; uint64_t State = 0; + static Material LoadFromShader(const char* vertPath, const char* fragPath); }; struct Camera diff --git a/src/game/shaders/frag.sc b/src/game/shaders/frag.sc index 0cf41bf..17823e8 100644 --- a/src/game/shaders/frag.sc +++ b/src/game/shaders/frag.sc @@ -1,24 +1,26 @@ $input v_color0 +$input v_normal $input v_uv0 $input v_wpos uniform vec4 u_time; +uniform vec4 u_testColor; #include "common.sh" float circle(vec2 uv, float radius) { float distSq = uv.x * uv.x + uv.y * uv.y; - // float result = distSq / (radius * radius); - float result = sqrt(distSq) / radius / 2; - // float result = sqrt(distSq) / radius; - return result < 0.4; + float result = sqrt(distSq) / radius; + // return result < 0.5; return clamp(1.0 - result, 0.0, 1.0); } -float calcBrightness(vec3 lightPos, vec3 vertPos) +float calcBrightness(vec3 lightPos, vec3 vertPos, vec3 normal) { - return clamp(1.0 - distance(lightPos, vertPos) * 0.01, 0.0, 1.0); + vec3 lightDir = normalize(lightPos - vertPos); + float diffuse = max(0.0, dot(lightDir, normal)); + return diffuse * clamp(1.0 - distance(lightPos, vertPos) * 0.01, 0.0, 1.0); } float circles(vec2 uv, float level, float subLevel, float brightness) @@ -43,15 +45,21 @@ float circles(vec2 uv, float level, float subLevel, float brightness) return min(sum, 1.0); } +vec3 desaturate(vec3 color) +{ + return vec3_splat(dot(color, vec3(0.33, 0.34, 0.33))); +} + void main() { - float testRadius = 50.0; + float testRadius = 30.0; float testSpeed = 1.0; vec3 testOffset = vec3(0.0, 0.0, 50.0); - float brightness = calcBrightness(testOffset + vec3(sin(u_time.x * testSpeed) * testRadius, 0.0, cos(u_time.x * testSpeed) * testRadius), v_wpos); - brightness = 0.2 + brightness * 0.8; + float3 lightPos = vec3(sin(u_time.x * testSpeed) * testRadius, 5.0, cos(u_time.x * testSpeed) * testRadius); + float brightness = calcBrightness(lightPos, v_wpos, v_normal); + // brightness = 0.1 + brightness * 0.9; - float baseScale = 10.0; + float baseScale = 2.0; float2 dx = ddx(v_uv0 * baseScale); float2 dy = ddy(v_uv0 * baseScale); float2x2 mat = float2x2(dx, dy); @@ -63,13 +71,19 @@ void main() float2 freq = sqrt(float2(qq + discriminant, qq - discriminant) / 2.0); float spacing = freq.y * exp2(2.0); - spacing = 4.0 / spacing; + spacing = 1.0 / spacing; spacing *= brightness; // TODO: check reference to see how to calculate this! - float spacingLog = max(log2(spacing), 1.0); + float spacingLog = max(log2(spacing), 0.0); int patternScaleLevel = floor(spacingLog); float patternFractional = spacingLog - patternScaleLevel; vec2 uv = v_uv0 * exp2(patternScaleLevel); float dither = circles(uv, patternScaleLevel, patternFractional, brightness); - gl_FragColor = lerp(dither, vec4(0.1, 0.1, 0.15, 1.0), vec4(0.9, 0.75, 0.3, 1.0)); + vec3 color = desaturate(u_testColor.xyz) * 0.01 + dither * u_testColor.xyz * 0.95; + vec3 smoothColor = brightness * u_testColor.xyz; + vec3 mixedColor = 0.1 * smoothColor + 0.9 * color; + gl_FragColor = vec4(mixedColor, 1.0); + // gl_FragColor = brightness; + // gl_FragColor = dither; + // gl_FragColor = u_testColor; } diff --git a/src/game/shaders/varying.def.sc b/src/game/shaders/varying.def.sc index 2cd00a9..cdd8009 100644 --- a/src/game/shaders/varying.def.sc +++ b/src/game/shaders/varying.def.sc @@ -1,7 +1,9 @@ vec4 v_color0 : COLOR0 = vec4(1.0, 1.0, 0.0, 1.0); +vec3 v_normal : NORMAL = vec3(0.0, 0.0, 1.0); vec2 v_uv0 : TEXCOORD0 = vec2(0.0, 0.0); vec3 v_wpos : TEXCOORD1 = vec3(0.0, 0.0, 0.0); vec3 a_position : POSITION; +vec3 a_normal : NORMAL; vec4 a_color0 : COLOR0; vec2 a_texcoord0 : TEXCOORD0; diff --git a/src/game/shaders/vert.sc b/src/game/shaders/vert.sc index 0a95563..746d180 100644 --- a/src/game/shaders/vert.sc +++ b/src/game/shaders/vert.sc @@ -1,5 +1,5 @@ -$input a_position, a_color0, a_texcoord0 -$output v_color0, v_uv0, v_wpos +$input a_position, a_normal, a_color0, a_texcoord0 +$output v_color0, v_normal, v_uv0, v_wpos #include "common.sh" @@ -9,4 +9,6 @@ void main() v_color0 = a_color0; v_uv0 = a_texcoord0; v_wpos = mul(u_model[0], vec4(a_position, 1.0)).xyz; + + v_normal = normalize(mul((mat3)u_model[0], a_normal)); }