-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add .vs GLSL vertex shader extension (#6536)
* Add missing GLSL vertex shader extension * Add .vs file for #6536 Sample GLSL file with a `.vs` extension from Google's filament repo: https://github.com/google/filament/blob/main/shaders/src/main.vs Licensed under Apache License 2.0 * Add another .vs file for #6536 From file from the https://github.com/FrostKiwi/Mirrorball/blob/main/src/shd/project.vs repo https://github.com/FrostKiwi/Mirrorball under the MIT licence. * Update lib/linguist/languages.yml --------- Co-authored-by: Colin Seymour <colin@github.com>
- Loading branch information
Showing
3 changed files
with
271 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2198,6 +2198,7 @@ GLSL: | |
- ".tese" | ||
- ".vert" | ||
- ".vrx" | ||
- ".vs" | ||
- ".vsh" | ||
- ".vshader" | ||
tm_scope: source.glsl | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
/* | ||
* This is the main vertex shader of surface materials. It can be invoked with | ||
* USE_OPTIMIZED_DEPTH_VERTEX_SHADER defined, and in this case we are guaranteed that the | ||
* DEPTH variant is active *AND* there is no custom vertex shader (i.e.: materialVertex() is | ||
* empty). | ||
* We can use this to remove all code that doesn't participate in the depth computation. | ||
*/ | ||
|
||
void main() { | ||
#if defined(FILAMENT_HAS_FEATURE_INSTANCING) | ||
# if defined(TARGET_METAL_ENVIRONMENT) || defined(TARGET_VULKAN_ENVIRONMENT) | ||
instance_index = gl_InstanceIndex; | ||
# else | ||
// PowerVR drivers don't initialize gl_InstanceID correctly if it's assigned to the varying | ||
// directly and early in the shader. Adding a bit of extra integer math, works around it. | ||
// Using an intermediate variable doesn't work because of spirv-opt. | ||
if (CONFIG_POWER_VR_SHADER_WORKAROUNDS) { | ||
instance_index = (1 + gl_InstanceID) - 1; | ||
} else { | ||
instance_index = gl_InstanceID; | ||
} | ||
# endif | ||
logical_instance_index = instance_index; | ||
#endif | ||
|
||
#if defined(VARIANT_HAS_INSTANCED_STEREO) | ||
#if !defined(FILAMENT_HAS_FEATURE_INSTANCING) | ||
#error Instanced stereo not supported at this feature level | ||
#endif | ||
// The lowest bit of the instance index represents the eye. | ||
// This logic must be updated if CONFIG_STEREOSCOPIC_EYES changes | ||
logical_instance_index = instance_index >> 1; | ||
#endif | ||
|
||
initObjectUniforms(); | ||
|
||
// Initialize the inputs to sensible default values, see material_inputs.vs | ||
#if defined(USE_OPTIMIZED_DEPTH_VERTEX_SHADER) | ||
|
||
// In USE_OPTIMIZED_DEPTH_VERTEX_SHADER mode, we can even skip this if we're already in | ||
// VERTEX_DOMAIN_DEVICE and we don't have VSM. | ||
#if !defined(VERTEX_DOMAIN_DEVICE) || defined(VARIANT_HAS_VSM) | ||
// Run initMaterialVertex to compute material.worldPosition. | ||
MaterialVertexInputs material; | ||
initMaterialVertex(material); | ||
// materialVertex() is guaranteed to be empty here, but we keep it to workaround some problem | ||
// in NVIDA drivers related to depth invariance. | ||
materialVertex(material); | ||
#endif | ||
|
||
#else // defined(USE_OPTIMIZED_DEPTH_VERTEX_SHADER) | ||
|
||
MaterialVertexInputs material; | ||
initMaterialVertex(material); | ||
|
||
#if defined(HAS_ATTRIBUTE_TANGENTS) | ||
// If the material defines a value for the "normal" property, we need to output | ||
// the full orthonormal basis to apply normal mapping | ||
#if defined(MATERIAL_NEEDS_TBN) | ||
// Extract the normal and tangent in world space from the input quaternion | ||
// We encode the orthonormal basis as a quaternion to save space in the attributes | ||
toTangentFrame(mesh_tangents, material.worldNormal, vertex_worldTangent.xyz); | ||
|
||
#if defined(VARIANT_HAS_SKINNING_OR_MORPHING) | ||
if ((object_uniforms_flagsChannels & FILAMENT_OBJECT_MORPHING_ENABLED_BIT) != 0) { | ||
#if defined(LEGACY_MORPHING) | ||
vec3 normal0, normal1, normal2, normal3; | ||
toTangentFrame(mesh_custom4, normal0); | ||
toTangentFrame(mesh_custom5, normal1); | ||
toTangentFrame(mesh_custom6, normal2); | ||
toTangentFrame(mesh_custom7, normal3); | ||
vec3 baseNormal = material.worldNormal; | ||
material.worldNormal += morphingUniforms.weights[0].xyz * (normal0 - baseNormal); | ||
material.worldNormal += morphingUniforms.weights[1].xyz * (normal1 - baseNormal); | ||
material.worldNormal += morphingUniforms.weights[2].xyz * (normal2 - baseNormal); | ||
material.worldNormal += morphingUniforms.weights[3].xyz * (normal3 - baseNormal); | ||
#else | ||
morphNormal(material.worldNormal); | ||
material.worldNormal = normalize(material.worldNormal); | ||
#endif | ||
} | ||
|
||
if ((object_uniforms_flagsChannels & FILAMENT_OBJECT_SKINNING_ENABLED_BIT) != 0) { | ||
skinNormal(material.worldNormal, mesh_bone_indices, mesh_bone_weights); | ||
skinNormal(vertex_worldTangent.xyz, mesh_bone_indices, mesh_bone_weights); | ||
} | ||
#endif | ||
|
||
// We don't need to normalize here, even if there's a scale in the matrix | ||
// because we ensure the worldFromModelNormalMatrix pre-scales the normal such that | ||
// all its components are < 1.0. This prevents the bitangent to exceed the range of fp16 | ||
// in the fragment shader, where we renormalize after interpolation | ||
vertex_worldTangent.xyz = getWorldFromModelNormalMatrix() * vertex_worldTangent.xyz; | ||
vertex_worldTangent.w = mesh_tangents.w; | ||
material.worldNormal = getWorldFromModelNormalMatrix() * material.worldNormal; | ||
#else // MATERIAL_NEEDS_TBN | ||
// Without anisotropy or normal mapping we only need the normal vector | ||
toTangentFrame(mesh_tangents, material.worldNormal); | ||
|
||
#if defined(VARIANT_HAS_SKINNING_OR_MORPHING) | ||
if ((object_uniforms_flagsChannels & FILAMENT_OBJECT_MORPHING_ENABLED_BIT) != 0) { | ||
#if defined(LEGACY_MORPHING) | ||
vec3 normal0, normal1, normal2, normal3; | ||
toTangentFrame(mesh_custom4, normal0); | ||
toTangentFrame(mesh_custom5, normal1); | ||
toTangentFrame(mesh_custom6, normal2); | ||
toTangentFrame(mesh_custom7, normal3); | ||
vec3 baseNormal = material.worldNormal; | ||
material.worldNormal += morphingUniforms.weights[0].xyz * (normal0 - baseNormal); | ||
material.worldNormal += morphingUniforms.weights[1].xyz * (normal1 - baseNormal); | ||
material.worldNormal += morphingUniforms.weights[2].xyz * (normal2 - baseNormal); | ||
material.worldNormal += morphingUniforms.weights[3].xyz * (normal3 - baseNormal); | ||
#else | ||
morphNormal(material.worldNormal); | ||
material.worldNormal = normalize(material.worldNormal); | ||
#endif | ||
} | ||
|
||
if ((object_uniforms_flagsChannels & FILAMENT_OBJECT_SKINNING_ENABLED_BIT) != 0) { | ||
skinNormal(material.worldNormal, mesh_bone_indices, mesh_bone_weights); | ||
} | ||
#endif | ||
|
||
material.worldNormal = getWorldFromModelNormalMatrix() * material.worldNormal; | ||
|
||
#endif // MATERIAL_HAS_ANISOTROPY || MATERIAL_HAS_NORMAL || MATERIAL_HAS_CLEAR_COAT_NORMAL | ||
#endif // HAS_ATTRIBUTE_TANGENTS | ||
|
||
// Invoke user code | ||
materialVertex(material); | ||
|
||
// Handle built-in interpolated attributes | ||
#if defined(HAS_ATTRIBUTE_COLOR) | ||
vertex_color = material.color; | ||
#endif | ||
#if defined(HAS_ATTRIBUTE_UV0) | ||
vertex_uv01.xy = material.uv0; | ||
#endif | ||
#if defined(HAS_ATTRIBUTE_UV1) | ||
vertex_uv01.zw = material.uv1; | ||
#endif | ||
|
||
// Handle user-defined interpolated attributes | ||
#if defined(VARIABLE_CUSTOM0) | ||
VARIABLE_CUSTOM_AT0 = material.VARIABLE_CUSTOM0; | ||
#endif | ||
#if defined(VARIABLE_CUSTOM1) | ||
VARIABLE_CUSTOM_AT1 = material.VARIABLE_CUSTOM1; | ||
#endif | ||
#if defined(VARIABLE_CUSTOM2) | ||
VARIABLE_CUSTOM_AT2 = material.VARIABLE_CUSTOM2; | ||
#endif | ||
#if defined(VARIABLE_CUSTOM3) | ||
VARIABLE_CUSTOM_AT3 = material.VARIABLE_CUSTOM3; | ||
#endif | ||
|
||
// The world position can be changed by the user in materialVertex() | ||
vertex_worldPosition.xyz = material.worldPosition.xyz; | ||
|
||
#ifdef HAS_ATTRIBUTE_TANGENTS | ||
vertex_worldNormal = material.worldNormal; | ||
#endif | ||
|
||
#if defined(VARIANT_HAS_SHADOWING) && defined(VARIANT_HAS_DIRECTIONAL_LIGHTING) | ||
vertex_lightSpacePosition = computeLightSpacePosition( | ||
vertex_worldPosition.xyz, vertex_worldNormal, | ||
frameUniforms.lightDirection, | ||
shadowUniforms.shadows[0].normalBias, | ||
shadowUniforms.shadows[0].lightFromWorldMatrix); | ||
#endif | ||
|
||
#endif // !defined(USE_OPTIMIZED_DEPTH_VERTEX_SHADER) | ||
|
||
vec4 position; | ||
|
||
#if defined(VERTEX_DOMAIN_DEVICE) | ||
// The other vertex domains are handled in initMaterialVertex()->computeWorldPosition() | ||
position = getPosition(); | ||
|
||
#if !defined(USE_OPTIMIZED_DEPTH_VERTEX_SHADER) | ||
#if defined(MATERIAL_HAS_CLIP_SPACE_TRANSFORM) | ||
position = getMaterialClipSpaceTransform(material) * position; | ||
#endif | ||
#endif // !USE_OPTIMIZED_DEPTH_VERTEX_SHADER | ||
|
||
#if defined(MATERIAL_HAS_VERTEX_DOMAIN_DEVICE_JITTERED) | ||
// Apply the clip-space transform which is normally part of the projection | ||
position.xy = position.xy * frameUniforms.clipTransform.xy + (position.w * frameUniforms.clipTransform.zw); | ||
#endif | ||
#else | ||
position = getClipFromWorldMatrix() * getWorldPosition(material); | ||
#endif | ||
|
||
#if defined(VERTEX_DOMAIN_DEVICE) | ||
// GL convention to inverted DX convention (must happen after clipSpaceTransform) | ||
position.z = position.z * -0.5 + 0.5; | ||
#endif | ||
|
||
#if defined(VARIANT_HAS_VSM) | ||
// For VSM, we use the linear light-space Z coordinate as the depth metric, which works for both | ||
// directional and spot lights and can be safely interpolated. | ||
// The value is guaranteed to be between [-znear, -zfar] by construction of viewFromWorldMatrix, | ||
// (see ShadowMap.cpp). | ||
// Use vertex_worldPosition.w which is otherwise not used to store the interpolated | ||
// light-space depth. | ||
highp float z = (getViewFromWorldMatrix() * getWorldPosition(material)).z; | ||
|
||
// rescale [near, far] to [0, 1] | ||
highp float depth = -z * frameUniforms.oneOverFarMinusNear - frameUniforms.nearOverFarMinusNear; | ||
|
||
// remap depth between -1 and 1 | ||
depth = depth * 2.0 - 1.0; | ||
|
||
vertex_worldPosition.w = depth; | ||
#endif | ||
|
||
// this must happen before we compensate for vulkan below | ||
vertex_position = position; | ||
|
||
#if defined(VARIANT_HAS_INSTANCED_STEREO) | ||
// This logic must be updated if CONFIG_STEREOSCOPIC_EYES changes | ||
// We're transforming a vertex whose x coordinate is within the range (-w to w). | ||
// To move it to the correct half of the viewport, we need to modify the x coordinate: | ||
// Eye 0 (left half): (-w to 0) | ||
// Eye 1 (right half): ( 0 to w) | ||
// It's important to do this after computing vertex_position. | ||
int eyeIndex = instance_index % 2; | ||
float eyeShift = float(eyeIndex) * 2.0f - 1.0f; // eye 0: -1.0, eye 1: 1.0 | ||
position.x = position.x * 0.5f + (position.w * 0.5 * eyeShift); | ||
|
||
// A fragment is clipped when gl_ClipDistance is negative (outside the clip plane). So, | ||
// Eye 0 should have a positive value when x is < 0 | ||
// -position.x | ||
// Eye 1 should have a positive value when x is > 0 | ||
// position.x | ||
FILAMENT_CLIPDISTANCE[0] = position.x * eyeShift; | ||
#endif | ||
|
||
#if defined(TARGET_VULKAN_ENVIRONMENT) | ||
// In Vulkan, clip space is Y-down. In OpenGL and Metal, clip space is Y-up. | ||
position.y = -position.y; | ||
#endif | ||
|
||
#if !defined(TARGET_VULKAN_ENVIRONMENT) && !defined(TARGET_METAL_ENVIRONMENT) | ||
// This is not needed in Vulkan or Metal because clipControl is always (1, 0) | ||
// (We don't use a dot() here because it workaround a spirv-opt optimization that in turn | ||
// causes a crash on PowerVR, see #5118) | ||
position.z = position.z * frameUniforms.clipControl.x + position.w * frameUniforms.clipControl.y; | ||
#endif | ||
|
||
// some PowerVR drivers crash when gl_Position is written more than once | ||
gl_Position = position; | ||
|
||
#if defined(VARIANT_HAS_INSTANCED_STEREO) | ||
// Fragment shaders filter out the stereo variant, so we need to set instance_index here. | ||
instance_index = logical_instance_index; | ||
#endif | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#version 100 | ||
attribute vec2 pos; | ||
attribute vec3 rayvtx; | ||
varying vec3 Ray; | ||
uniform vec4 split; | ||
|
||
void main() | ||
{ | ||
Ray = rayvtx; | ||
gl_Position = vec4(pos * vec2(split.z, split.w) + vec2(split.x, split.y), | ||
0.0, 1.0); | ||
} |