diff --git a/aggregated-graphics-samples.sln b/aggregated-graphics-samples.sln index 224e2ee..c5a393c 100644 --- a/aggregated-graphics-samples.sln +++ b/aggregated-graphics-samples.sln @@ -79,6 +79,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "displacement-mapping", "dis {67B01ECD-2613-4FA0-84F7-87F5BCF40EB1} = {67B01ECD-2613-4FA0-84F7-87F5BCF40EB1} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "self-shadowing", "self-shadowing\self-shadowing.vcxproj", "{1C2F65F9-6268-4271-A0F7-EE3E6DBF8F9E}" + ProjectSection(ProjectDependencies) = postProject + {8D9D4A3E-439A-4210-8879-259B20D992CA} = {8D9D4A3E-439A-4210-8879-259B20D992CA} + {51CC36B3-921E-4853-ACD5-CB6CBC27FBA1} = {51CC36B3-921E-4853-ACD5-CB6CBC27FBA1} + {67B01ECD-2613-4FA0-84F7-87F5BCF40EB1} = {67B01ECD-2613-4FA0-84F7-87F5BCF40EB1} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -183,6 +190,14 @@ Global {6642AD41-5A38-45DC-9646-A265B73E0858}.Release|x64.Build.0 = Release|x64 {6642AD41-5A38-45DC-9646-A265B73E0858}.Release|x86.ActiveCfg = Release|Win32 {6642AD41-5A38-45DC-9646-A265B73E0858}.Release|x86.Build.0 = Release|Win32 + {1C2F65F9-6268-4271-A0F7-EE3E6DBF8F9E}.Debug|x64.ActiveCfg = Debug|x64 + {1C2F65F9-6268-4271-A0F7-EE3E6DBF8F9E}.Debug|x64.Build.0 = Debug|x64 + {1C2F65F9-6268-4271-A0F7-EE3E6DBF8F9E}.Debug|x86.ActiveCfg = Debug|Win32 + {1C2F65F9-6268-4271-A0F7-EE3E6DBF8F9E}.Debug|x86.Build.0 = Debug|Win32 + {1C2F65F9-6268-4271-A0F7-EE3E6DBF8F9E}.Release|x64.ActiveCfg = Release|x64 + {1C2F65F9-6268-4271-A0F7-EE3E6DBF8F9E}.Release|x64.Build.0 = Release|x64 + {1C2F65F9-6268-4271-A0F7-EE3E6DBF8F9E}.Release|x86.ActiveCfg = Release|Win32 + {1C2F65F9-6268-4271-A0F7-EE3E6DBF8F9E}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/assets/textures/storage-container2/storage-container2-albedo.dds b/assets/textures/storage-container2/storage-container2-albedo.dds new file mode 100644 index 0000000..7b8ef21 Binary files /dev/null and b/assets/textures/storage-container2/storage-container2-albedo.dds differ diff --git a/assets/textures/storage-container2/storage-container2-normal-dx.dds b/assets/textures/storage-container2/storage-container2-normal-dx.dds new file mode 100644 index 0000000..64e350a Binary files /dev/null and b/assets/textures/storage-container2/storage-container2-normal-dx.dds differ diff --git a/assets/textures/storage-container2/storage-container2-roughness.dds b/assets/textures/storage-container2/storage-container2-roughness.dds new file mode 100644 index 0000000..76fc867 Binary files /dev/null and b/assets/textures/storage-container2/storage-container2-roughness.dds differ diff --git a/framework/graphicsApp.cpp b/framework/graphicsApp.cpp index 8bccc42..333f4a0 100644 --- a/framework/graphicsApp.cpp +++ b/framework/graphicsApp.cpp @@ -270,8 +270,11 @@ void GraphicsApp::updateObjectTransforms(const std::vectorupdateView(); - lightViewProj->updateProjection(); + if (lightViewProj) + { + lightViewProj->updateView(); + lightViewProj->updateProjection(); + } magma::helpers::mapScoped(lightSource, [this](auto *light) { diff --git a/framework/textureLoader.cpp b/framework/textureLoader.cpp index 19da98b..ff265a8 100644 --- a/framework/textureLoader.cpp +++ b/framework/textureLoader.cpp @@ -2,17 +2,17 @@ #include "magma/magma.h" #include "gliml/gliml.h" -static VkFormat blockCompressedFormat(const gliml::context& ctx) +static VkFormat blockCompressedFormat(const gliml::context& ctx, bool sRGB) { const int internalFormat = ctx.image_internal_format(); switch (internalFormat) { case GLIML_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return VK_FORMAT_BC1_RGBA_UNORM_BLOCK; + return sRGB ? VK_FORMAT_BC1_RGBA_SRGB_BLOCK : VK_FORMAT_BC1_RGBA_UNORM_BLOCK; case GLIML_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - return VK_FORMAT_BC2_UNORM_BLOCK; + return sRGB ? VK_FORMAT_BC2_SRGB_BLOCK : VK_FORMAT_BC2_UNORM_BLOCK; case GLIML_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - return VK_FORMAT_BC3_UNORM_BLOCK; + return sRGB ? VK_FORMAT_BC3_SRGB_BLOCK : VK_FORMAT_BC3_UNORM_BLOCK; default: throw std::invalid_argument("unknown block compressed format"); return VK_FORMAT_UNDEFINED; @@ -23,12 +23,12 @@ static VkFormat blockCompressedExtFormat(unsigned int fourCC) { switch (fourCC) { - // ATI2 + // ATI1 case MAKEFOURCC('B', 'C', '4', 'U'): return VK_FORMAT_BC4_UNORM_BLOCK; case MAKEFOURCC('B', 'C', '4', 'S'): return VK_FORMAT_BC4_SNORM_BLOCK; - // ATI1 + // ATI2 case MAKEFOURCC('B', 'C', '5', 'U'): return VK_FORMAT_BC5_UNORM_BLOCK; case MAKEFOURCC('B', 'C', '5', 'S'): @@ -92,7 +92,8 @@ static VkFormat loadDxtTextureExt(const gliml::dds_header *hdr, VkExtent2D& exte return format; } -std::shared_ptr loadDxtTexture(std::shared_ptr cmdCopy, const std::string& filename) +std::shared_ptr loadDxtTexture(std::shared_ptr cmdCopy, const std::string& filename, + bool sRGB /* false */) { std::ifstream file("../assets/textures/" + filename, std::ios::in | std::ios::binary | std::ios::ate); if (!file.is_open()) @@ -112,7 +113,7 @@ std::shared_ptr loadDxtTexture(std::shared_ptr(size))) { // Setup texture data description - format = blockCompressedFormat(ctx); + format = blockCompressedFormat(ctx, sRGB); extent.width = static_cast(ctx.image_width(0, 0)); extent.height = static_cast(ctx.image_height(0, 0)); for (int level = 1; level < ctx.num_mipmaps(0); ++level) @@ -128,10 +129,10 @@ std::shared_ptr loadDxtTexture(std::shared_ptrddspf.dwFourCC) { - case MAKEFOURCC('B', 'C', '4', 'U'): // ATI2 - case MAKEFOURCC('B', 'C', '4', 'S'): // ATI2 - case MAKEFOURCC('B', 'C', '5', 'U'): // ATI1 - case MAKEFOURCC('B', 'C', '5', 'S'): // ATI1 + case MAKEFOURCC('B', 'C', '4', 'U'): // ATI1 + case MAKEFOURCC('B', 'C', '4', 'S'): // ATI1 + case MAKEFOURCC('B', 'C', '5', 'U'): // ATI2 + case MAKEFOURCC('B', 'C', '5', 'S'): // ATI2 format = loadDxtTextureExt(hdr, extent, mipOffsets, baseMipOffset); break; default: diff --git a/framework/textureLoader.h b/framework/textureLoader.h index d7b80d5..1dcf82a 100644 --- a/framework/textureLoader.h +++ b/framework/textureLoader.h @@ -8,4 +8,5 @@ namespace magma class CommandBuffer; } -std::shared_ptr loadDxtTexture(std::shared_ptr device, const std::string& filename); +std::shared_ptr loadDxtTexture(std::shared_ptr device, const std::string& filename, + bool sRGB = false); diff --git a/screenshots/self-shadowing.jpg b/screenshots/self-shadowing.jpg new file mode 100644 index 0000000..c0855cb Binary files /dev/null and b/screenshots/self-shadowing.jpg differ diff --git a/self-shadowing/self-shadowing.cpp b/self-shadowing/self-shadowing.cpp new file mode 100644 index 0000000..1680313 --- /dev/null +++ b/self-shadowing/self-shadowing.cpp @@ -0,0 +1,201 @@ +#include "graphicsApp.h" +#include "colorTable.h" +#include "textureLoader.h" +#include "quadric/include/cube.h" +#include "quadric/include/sphere.h" + +class SelfShadowing : public GraphicsApp +{ + struct Constants + { + VkBool32 selfShadowing; + }; + + std::unique_ptr box; + std::unique_ptr sphere; + std::shared_ptr diffuseMap; + std::shared_ptr normalMap; + std::shared_ptr specularMap; + std::shared_ptr phongPipeline; + std::shared_ptr spherePipeline; + DescriptorSet phongDescriptor; + DescriptorSet fillDescriptor; + + Constants constants = {false}; + +public: + explicit SelfShadowing(const AppEntry& entry): + GraphicsApp(entry, TEXT("Self-shadowing"), 1280, 720, true) + { + setupViewProjection(); + createTransformBuffer(2); + createMeshObjects(); + loadTexture(); + setupDescriptorSets(); + setupGraphicsPipelines(); + + renderScene(drawCmdBuffer); + blit(msaaFramebuffer->getColorView(), FrontBuffer); + blit(msaaFramebuffer->getColorView(), BackBuffer); + } + + virtual void render(uint32_t bufferIndex) override + { + updateTransforms(); + submitCommandBuffers(bufferIndex); + std::this_thread::sleep_for(std::chrono::milliseconds(2)); // Cap fps + } + + virtual void onKeyDown(char key, int repeat, uint32_t flags) override + { + switch (key) + { + case AppKey::Space: + constants.selfShadowing = !constants.selfShadowing; + setupGraphicsPipelines(); + renderScene(drawCmdBuffer); + break; + } + updateTransforms(); + updateLightSource(); + VulkanApp::onKeyDown(key, repeat, flags); + } + + virtual void onMouseWheel(float distance) override + { + float step = distance * 0.2f; + float z = viewProj->getPosition().z; + if ((z + step < -3.3f) && (z + step > -15.f)) + viewProj->translate(0.f, 0.f, step); + updateViewProjTransforms(); + } + + virtual void updateLightSource() + { + magma::helpers::mapScoped(lightSource, + [this](auto *light) + { + constexpr float ambientFactor = 0.2f; + light->viewPosition = viewProj->getView() * lightViewProj->getPosition(); + light->ambient = ivory * ambientFactor; + light->diffuse = ivory; + light->specular = old_lace; + }); + } + + void setupViewProjection() + { + viewProj = std::make_unique(); + viewProj->setPosition(0.f, 0.f, -5.f); + viewProj->setFocus(0.f, 0.f, 0.f); + viewProj->setFieldOfView(45.f); + viewProj->setNearZ(1.f); + viewProj->setFarZ(100.f); + viewProj->setAspectRatio(width / (float)height); + viewProj->updateView(); + viewProj->updateProjection(); + + lightViewProj = std::make_unique(); + lightViewProj->setPosition(-1.f, 1.f, -2.f); + + updateViewProjTransforms(); + } + + void updateTransforms() + { + rapid::matrix lightTransform = rapid::translation(rapid::vector3(lightViewProj->getPosition())); + const std::vector> transforms = { + arcball->transform(), + lightTransform + }; + updateObjectTransforms(transforms); + } + + void createMeshObjects() + { + box = std::make_unique(cmdCopyBuf); + sphere = std::make_unique(0.02f, 8, 8, true, cmdCopyBuf); + } + + void loadTexture() + { // https://freepbr.com/materials/storage-container2/ + diffuseMap = loadDxtTexture(cmdCopyImg, "storage-container2/storage-container2-albedo.dds", true); + normalMap = loadDxtTexture(cmdCopyImg, "storage-container2/storage-container2-normal-dx.dds"); + specularMap = loadDxtTexture(cmdCopyImg, "storage-container2/storage-container2-roughness.dds"); + } + + void setupDescriptorSets() + { + using namespace magma::bindings; + using namespace magma::descriptors; + // Bump shader + phongDescriptor.layout = std::shared_ptr(new magma::DescriptorSetLayout(device, + { + VertexFragmentStageBinding(0, DynamicUniformBuffer(1)), + FragmentStageBinding(1, UniformBuffer(1)), + FragmentStageBinding(2, UniformBuffer(1)), + FragmentStageBinding(3, CombinedImageSampler(1)), + FragmentStageBinding(4, CombinedImageSampler(1)), + FragmentStageBinding(5, CombinedImageSampler(1)) + })); + phongDescriptor.set = descriptorPool->allocateDescriptorSet(phongDescriptor.layout); + phongDescriptor.set->update(0, transforms); + phongDescriptor.set->update(1, viewProjTransforms); + phongDescriptor.set->update(2, lightSource); + phongDescriptor.set->update(3, diffuseMap, anisotropicClampToEdge); + phongDescriptor.set->update(4, normalMap, anisotropicClampToEdge); + phongDescriptor.set->update(5, specularMap, anisotropicClampToEdge); + // Fill shader + fillDescriptor.layout = std::shared_ptr(new magma::DescriptorSetLayout(device, + { + VertexStageBinding(0, DynamicUniformBuffer(1)) + })); + fillDescriptor.set = descriptorPool->allocateDescriptorSet(fillDescriptor.layout); + fillDescriptor.set->update(0, transforms); + } + + void setupGraphicsPipelines() + { + auto specialization(std::make_shared(constants, + magma::SpecializationEntry(0, &Constants::selfShadowing))); + phongPipeline = createCommonSpecializedPipeline( + "transform.o", "phong.o", + std::move(specialization), + box->getVertexInput(), + phongDescriptor.layout); + if (!spherePipeline) + { + spherePipeline = createCommonPipeline( + "transform.o", "fill.o", + sphere->getVertexInput(), + fillDescriptor.layout); + } + } + + void renderScene(std::shared_ptr cmdBuffer) + { + cmdBuffer->begin(); + { + cmdBuffer->beginRenderPass(msaaFramebuffer->getRenderPass(), msaaFramebuffer->getFramebuffer(), + { + magma::ClearColor(0.1f, 0.243f, 0.448f, 1.f), + magma::clears::depthOne + }); + { + cmdBuffer->bindPipeline(phongPipeline); + cmdBuffer->bindDescriptorSet(phongPipeline, phongDescriptor.set, transforms->getDynamicOffset(0)); + box->draw(cmdBuffer); + cmdBuffer->bindPipeline(spherePipeline); + cmdBuffer->bindDescriptorSet(spherePipeline, fillDescriptor.set, transforms->getDynamicOffset(1)); + sphere->draw(cmdBuffer); + } + cmdBuffer->endRenderPass(); + } + cmdBuffer->end(); + } +}; + +std::unique_ptr appFactory(const AppEntry& entry) +{ + return std::unique_ptr(new SelfShadowing(entry)); +} diff --git a/self-shadowing/self-shadowing.vcxproj b/self-shadowing/self-shadowing.vcxproj new file mode 100644 index 0000000..1f4d61a --- /dev/null +++ b/self-shadowing/self-shadowing.vcxproj @@ -0,0 +1,186 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {1C2F65F9-6268-4271-A0F7-EE3E6DBF8F9E} + template + 10.0.16299.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + true + _DEBUG;VK_USE_PLATFORM_WIN32_KHR;%(PreprocessorDefinitions) + $(VK_SDK_PATH)\Include;..\third-party;..\framework + + + vulkan-1.lib;magma.lib;quadric.lib;framework.lib;Shcore.lib;%(AdditionalDependencies) + $(VK_SDK_PATH)\Lib32;..\Debug + Windows + + + + + Level3 + Disabled + true + true + _DEBUG;VK_USE_PLATFORM_WIN32_KHR;%(PreprocessorDefinitions) + $(VK_SDK_PATH)\Include;..\third-party;..\framework + + + Windows + vulkan-1.lib;magma.lib;quadric.lib;framework.lib;Shcore.lib;%(AdditionalDependencies) + $(VK_SDK_PATH)\Lib;..\x64\Debug + + + + + Level3 + MaxSpeed + true + true + true + true + NDEBUG;VK_USE_PLATFORM_WIN32_KHR;%(PreprocessorDefinitions) + $(VK_SDK_PATH)\Include;..\third-party;..\framework + MultiThreaded + + + true + true + vulkan-1.lib;magma.lib;quadric.lib;framework.lib;Shcore.lib;%(AdditionalDependencies) + $(VK_SDK_PATH)\Lib32;..\Release + Windows + + + + + Level3 + MaxSpeed + true + true + true + true + NDEBUG;VK_USE_PLATFORM_WIN32_KHR;%(PreprocessorDefinitions) + $(VK_SDK_PATH)\Include;..\third-party;..\framework + MultiThreaded + + + true + true + Windows + vulkan-1.lib;magma.lib;quadric.lib;framework.lib;Shcore.lib;%(AdditionalDependencies) + $(VK_SDK_PATH)\Lib;..\x64\Release + + + + + + + + Document + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + %(Filename).o + %(Filename).o + %(Filename).o + %(Filename).o + + + + + Document + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + %(Filename).o + %(Filename).o + %(Filename).o + %(Filename).o + + + Document + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + $(VK_SDK_PATH)\Bin32\glslangValidator.exe -V %(FullPath) -I..\framework\shaders -o %(Filename).o + %(Filename).o + %(Filename).o + %(Filename).o + %(Filename).o + + + + + + \ No newline at end of file diff --git a/self-shadowing/self-shadowing.vcxproj.filters b/self-shadowing/self-shadowing.vcxproj.filters new file mode 100644 index 0000000..cf7545a --- /dev/null +++ b/self-shadowing/self-shadowing.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/self-shadowing/shaders/fill.frag b/self-shadowing/shaders/fill.frag new file mode 100644 index 0000000..dd3e227 --- /dev/null +++ b/self-shadowing/shaders/fill.frag @@ -0,0 +1,8 @@ +#version 450 + +layout(location = 0) out vec3 oColor; + +void main() +{ + oColor = vec3(1, 1, 0); +} diff --git a/self-shadowing/shaders/phong.frag b/self-shadowing/shaders/phong.frag new file mode 100644 index 0000000..ce1f6fb --- /dev/null +++ b/self-shadowing/shaders/phong.frag @@ -0,0 +1,74 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable +#include "common/transforms.h" +#include "common/reconstruct.h" +#include "common/cotangentFrame.h" +#include "common/brdf/phong.h" +#include "common/sRGB.h" + +layout(constant_id = 0) const bool c_selfShadowing = false; + +layout(binding = 2) uniform Light +{ + vec4 viewPos; + vec4 ambient; + vec4 diffuse; + vec4 specular; +} light; + +layout(binding = 3) uniform sampler2D diffuseMap; +layout(binding = 4) uniform sampler2D normalMap; +layout(binding = 5) uniform sampler2D specularMap; + +layout(location = 0) in vec3 position; +layout(location = 1) in vec3 viewPos; +layout(location = 2) in vec3 normal; +layout(location = 3) in vec3 viewNormal; +layout(location = 4) in vec2 texCoord; + +layout(location = 0) out vec3 oColor; + +float selfshadowing(vec3 n, vec3 l, float c) +{ + float NdL = dot(n, l); + return (NdL > c) ? 1. : + (NdL <= 0.) ? 0. : + 1./c * NdL; +} + +void main() +{ + vec2 nxy = texture(normalMap, texCoord).xy; + vec3 albedo = texture(diffuseMap, texCoord).rgb; + float shininess = texture(specularMap, texCoord).x; + + // compute per-pixel cotangent frame + vec3 N = normalize(normal); + mat3 TBN = cotangentFrame(N, position, texCoord); + + // transform from texture space to object space + vec3 micronormal = TBN * reconstructNormal(nxy); + // transform from object space to view space + micronormal = mat3(normalMatrix) * micronormal; + + vec3 n = normalize(micronormal); + vec3 l = normalize(light.viewPos.xyz - viewPos); + vec3 v = -normalize(viewPos); + + float self = 1.; + if (c_selfShadowing) + { // compute self-shadowing factor + vec3 n = normalize(viewNormal); + self = selfshadowing(n, l, 1./8.); + } + + vec3 srgbAlbedo = sRGB(albedo); + vec3 ambient = linear(0.2 * srgbAlbedo); + vec3 specular = linear(2. * srgbAlbedo); + + oColor = phong(n, l, v, + ambient, light.ambient.rgb, + albedo, light.diffuse.rgb, + specular, light.specular.rgb, + shininess * 16., self); +} diff --git a/self-shadowing/shaders/transform.vert b/self-shadowing/shaders/transform.vert new file mode 100644 index 0000000..24d0bd4 --- /dev/null +++ b/self-shadowing/shaders/transform.vert @@ -0,0 +1,27 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable +#include "common/transforms.h" + +layout(location = 0) in vec4 position; +layout(location = 1) in vec3 normal; +layout(location = 2) in vec2 texCoord; + +layout(location = 0) out vec3 oPos; +layout(location = 1) out vec3 oViewPos; +layout(location = 2) out vec3 oNormal; +layout(location = 3) out vec3 oViewNormal; +layout(location = 4) out vec2 oTexCoord; + +out gl_PerVertex{ + vec4 gl_Position; +}; + +void main() +{ + oPos = position.xyz; + oViewPos = (worldView * position).xyz; + oNormal = normal; + oViewNormal = mat3(normalMatrix) * normal; + oTexCoord = texCoord; + gl_Position = worldViewProj * position; +} diff --git a/third-party/magma b/third-party/magma index 7506e5b..c217aad 160000 --- a/third-party/magma +++ b/third-party/magma @@ -1 +1 @@ -Subproject commit 7506e5b14ddc79e4ba83b8fa2b21375ba63926da +Subproject commit c217aad97f060bb145c20bd7819edf238d47001a