VglShaderMaterial
A material for drawing geometries with custom vertex or fragment shaders, corresponding to THREE.ShaderMaterial.
Properties of VglMaterial are also available as a mixin.
Note that some of these properties are not efficient to update. See here for some caveats about updating material state.
props
-
definesObject (optional)default: {}Defines custom constants using
#definedirectives within the GLSL code for both the vertex shader and the fragment shader; each key/value pair yields another directive:defines: { FOO: 15, BAR: true }yields the lines
#define FOO 15 #define BAR truein the GLSL code.
-
fogboolean (optional)default: falseDefine whether the material color is affected by global fog settings; true to pass fog uniforms to the shader. Note that changing this value will cause the material to be reconstructed, so be aware of performance if using this reactively. Also note that when using this, THREE expects fog-related uniforms to be defined on your material; you can use something like the following to include them:
uniforms: THREE.UniformsUtils.merge([ THREE.UniformsLib['fog'], { other uniforms... } ]), -
fragment-shaderstring (optional)default: The default fragment shader provided by three.jsFragment shader GLSL code. This is the actual code for the shader.
-
lightsboolean (optional)default: falseDefines whether this material uses lighting; true to pass uniform data related to lighting to this shader. Note that changing this value will cause the material to be reconstructed, so be aware of performance if using this reactively. Also note that when using this, THREE expects lighting-related uniforms to be defined on your material; you can use something like the following to include them:
uniforms: THREE.UniformsUtils.merge([ THREE.UniformsLib['lights'], { other uniforms... } ]), -
linewidthfloat (optional)default: 1Controls wireframe thickness. Due to limitations of the OpenGL Core Profile with the WebGL renderer on most platforms
linewidthwill always be 1 regardless of the set value. -
flat-shadingboolean (optional)default: falseDefine whether the material is rendered with flat shading.
-
uniformsObject (optional)default: [object Object]An object of the form:
{ "uniform1": { value: 1.0 }, "uniform2": { value: 2 } }specifying the uniforms to be passed to the shader code; keys are uniform names, values are definitions of the form
{ value: 1.0 }where value is the value of the uniform. Names must match the name of the uniform, as defined in the GLSL code. Note that uniforms are refreshed on every frame, so updating the value of the uniform will immediately update the value available to the GLSL code.
-
vertex-shaderstring (optional)default: The default vertex shader provided by three.jsVertex shader GLSL code. This is the actual code for the shader.
-
wireframeboolean (optional)default: falseRender geometry as wireframe (using
GL_LINESinstead ofGL_TRIANGLES). -
wireframe-linewidthfloat (optional)default: 1Controls wireframe thickness. Due to limitations of the OpenGL Core Profile with the WebGL renderer on most platforms
linewidthwill always be 1 regardless of the set value.
computed properties
-
instThe THREE.ShaderMaterial instance.
dependencies:
fog,lights
Example
<template>
<div>
<vgl-renderer
antialias
camera="camera"
scene="scene"
>
<vgl-scene name="scene">
<vgl-icosahedron-geometry
name="geo"
radius="1"
detail="5"
/>
<vgl-shader-material
ref="mat"
name="mat"
wireframe
:defines="defines"
:uniforms="uniforms"
:vertex-shader="vertexShader"
:fragment-shader="fragmentShader"
/>
<vgl-mesh
geometry="geo"
material="mat"
/>
</vgl-scene>
<vgl-perspective-camera
orbit-position="5 0.8 0.2"
name="camera"
/>
</vgl-renderer>
<aside class="control-panel">
<section>
<h3>Shaders</h3>
<label>
Vertex Shader [<a @click="vertShaderShown = !vertShaderShown">
{{ vertShaderShown ? 'Hide' : 'Show' }}
</a>]
</label>
<textarea
v-model="vertexShader"
:style="{display: vertShaderShown ? "block" : "none"}"
rows="14"
cols="50"
/>
<label>
Fragment Shader [<a @click="fragShaderShown = !fragShaderShown">
{{ fragShaderShown ? 'Hide' : 'Show' }}
</a>]
</label>
<textarea
v-model="fragmentShader"
:style="{display: fragShaderShown ? "block" : "none"}"
rows="14"
cols="50"
/>
</section>
<section>
<h3>Vert Shader Uniforms</h3>
<table>
<tr>
<td>Offset</td><td>
<input
v-model.number="uniforms.waveOffset.value"
class="slider"
type="range"
max="2"
step="0.01"
>
</td>
</tr>
<tr>
<td>Amplitude</td><td>
<input
v-model.number="uniforms.waveAmp.value"
class="slider"
type="range"
max="2"
step="0.01"
>
</td>
</tr>
<tr>
<td>Frequency</td><td>
<input
v-model.number="uniforms.waveFreq.value"
class="slider"
type="range"
max="50"
>
</td>
</tr>
</table>
<label>
<h3>Frag Shader Uniforms</h3>
Frag Color
<select v-model.number="uniforms.displayColor.value">
<option
value="0"
selected
>Cartesian</option>
<option value="1">Spherical</option>
<option value="2">Depth</option>
</select>
</label>
</section>
</aside>
</div>
</template>
<script>
export default {
data: () => ({
vertShaderShown: false,
fragShaderShown: false,
defines: {
COLOR_CARTESIAN: 0,
COLOR_SPHERICAL: 1,
COLOR_DEPTH: 2,
},
uniforms: {
waveOffset: { value: 0.0 },
waveAmp: { value: 0.2 },
waveFreq: { value: 10 },
displayColor: { value: 0 },
},
vertexShader: `
uniform float waveOffset;
uniform float waveAmp;
uniform float waveFreq;
varying vec4 vCartesian;
varying vec4 vSpherical;
void main() {
float r = length(position);
float theta = acos(position.y / r); // inclination
float phi = atan(position.z, position.x); // azimuth
float finalR = r + sin((theta + waveOffset) * waveFreq) * waveAmp;
vec4 finalPos = vec4(
finalR * sin(theta) * cos(phi),
finalR * cos(theta),
finalR * sin(theta) * sin(phi),
1.0
);
gl_Position = projectionMatrix * modelViewMatrix * finalPos;
const float PI = 3.141592654;
vCartesian = finalPos;
vSpherical = vec4( // normalize values to [0, 1]
r,
theta / PI,
((phi / PI) + 1.0) / 2.0,
1.0
);
}
`.trim(),
fragmentShader: `
uniform int displayColor;
varying vec4 vSpherical;
varying vec4 vCartesian;
void main() {
if (displayColor == COLOR_CARTESIAN) {
gl_FragColor = vCartesian;
} else if (displayColor == COLOR_SPHERICAL) {
gl_FragColor = vSpherical;
} else if (displayColor == COLOR_DEPTH) {
float depth = gl_FragCoord.z * gl_FragCoord.w;
gl_FragColor = vec4(vec3(depth), 1.0);
}
}
`.trim(),
}),
};
</script>