I have the following shader with two passes and scene blend but I see those faces marked in black..
how would I maintain transparency and not see these faces in the picture ?
The material does two passes on cull faces anticlockwise and the other pass cull faces clockwise.
The shader does a dot product between the normal and the camera position and then modulate the transparency based on that result.
#version 100
precision highp int;
precision highp float;
uniform float time;
uniform float touchX;
uniform float touchY;
uniform float touchZ;
uniform float line;
varying float lightDiffuse;
void main()
{
float rampLight =lightDiffuse;
float light = (1.0 - rampLight) * 1.0;
vec4 lightColor = vec4(1.0,1.0,1.0, 1.0);
vec4 diffuseColor = lightColor * light;
vec4 c;
if(rampLight < 0.0 )
{
discard;
}
diffuseColor = smoothstep(vec4(0.0, 0.0, 0.0, 0.0), vec4(0.8, 0.8, 0.8, 0.8), vec4(diffuseColor));
gl_FragColor = diffuseColor;
}
material Router
{
technique
{
pass
{
scene_blend alpha_blend
depth_write on
depth_check on
cull_hardware anticlockwise
vertex_program_ref movingline_101_vs
{
}
fragment_program_ref movingline_101_fs
{
}
}
pass
{
scene_blend alpha_blend
cull_hardware clockwise
depth_write on
depth_check on
vertex_program_ref movingline_101_vs
{
}
fragment_program_ref movingline_101_fs
{
}
}
}
}
Update:
material Router
{
technique
{
pass
{
depth_write on
vertex_program_ref pass_101_vs
{
}
fragment_program_ref pass_101_fs
{
}
}
pass
{
depth_write off
depth_fun equal
scene_blend add
vertex_program_ref movingline_101_vs
{
}
fragment_program_ref movingline_101_fs
{
}
}
}
}
pass shader
void main()
{
gl_FragColor = vec4(0.0,0.0,0.0,0.0);
}
main shader:
#version 120
precision highp int;
precision highp float;
uniform float time;
uniform float touchX;
uniform float touchY;
uniform float touchZ;
uniform float line;
varying float lightDiffuse;
void main()
{
float rampLight =lightDiffuse;
float light = (1.0 - rampLight) * 1.0;
vec4 lightColor = vec4(1.0,1.0,1.0, 1.0);
vec4 diffuseColor = lightColor * light;
diffuseColor = smoothstep(vec4(0.0, 0.0, 0.0, 0.0), vec4(0.9, 0.9, 0.9, 0.9), vec4(diffuseColor));
gl_FragColor = diffuseColor;
}
If you're just trying to render something with transparency, but without being able to see the faces which would be occluded if it was opaque, then a common simple technique is to prime the depth buffer first.
Pass 1: Write to just the depth buffer. Easiest way to achieve this is by rendering with blending on and a shader that just outputs vec4(0.0, 0.0, 0.0, 0.0) for every fragment. There may be more efficient ways to prime the depth buffer (e.g. using glColorMask instead of blending), but this approach is simple and probably good enough.
Pass 2: Render with a depth test of GL_EQUAL. Use whatever shader you like.
Performance note: discard is often slower than just outputting vec4(0.0, 0.0, 0.0, 0.0) for pixels you want to be transparent on mobile hardware, so avoid discard unless you really need it - in this case you don't need it.
Related
I made 1000 points and gave them coordinates to create a ring shape. I then gave a shader material to the points and pointed to the vertex and fragment shaders.
Vertex Shader:
const vertexShader = `
uniform float uTime;
uniform float uRadius;
varying vec3 vColor;
varying float vDistance;
void main() {
vDistance = distance(position, vec3(0.0));
// Do Not Touch
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 );
gl_PointSize = 5.0;
}
`
export default vertexShader
Fragment Shader:
const fragmentShader = `
uniform float uDistance[1000];
uniform float uResolutionWidth;
uniform float uResolutionHeight;
varying float vDistance;
void main() {
vec2 resolution = vec2(uResolutionWidth, uResolutionHeight);
vec2 st = gl_FragCoord.xy/resolution;
float pct = distance(st, vec2(1.0));
vec3 color = vec3(mix(vec3(1.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0), pct));
gl_FragColor = vec4( color, 1.0 );
}
`
export default fragmentShader
What I had wanted to do was assign a color to each point based on its distance to the origin. However I realized what I did is assign a color based on the pointer distance to the camera, or at least it's what its looking like
EDIT:
I tried to pass along a varying vDistance like so
varying vec3 vRealPosition;
void main() {
vDistance = distance(position, vec3(0.0));
vColor = mix(vec3(1.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0), vDistance);
vRealPosition = position;
// Do Not Touch
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 );
gl_PointSize = 5.0;
}
But when I used it in fragment shader all points are just blue
varying vec3 vRealPosition;
void main() {
vec2 resolution = vec2(uResolutionWidth, uResolutionHeight);
vec2 st = gl_FragCoord.xy/resolution;
float pct = distance(vRealPosition, vec3(0.0));
vec3 color = vec3(mix(vec3(1.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0), pct));
gl_FragColor = vec4( vColor, 1.0 );
}
I want to implement a horizontal image slider in three.js.
This is the example of a vertical slider.
I want to implement the following image. (horizontal slider). This is the example of a horizontal slider.
vertexShader() {
return `
varying vec2 vUv;
varying vec3 vPosition;
void main() {
vUv = uv;
vPosition = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`
}
fragmentShader() {
return `
varying vec2 vUv;
varying vec3 vPosition;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform float divider;
uniform float zoomFactor;
uniform bool hidden;
void main() {
float dividerWidth;
if (hidden) {
dividerWidth = 0.0;
} else {
dividerWidth = 0.03 / zoomFactor;
}
if (vPosition.x > divider + dividerWidth) {
gl_FragColor = texture2D(tex1, vUv);
} else if (vPosition.x < divider - dividerWidth) {
gl_FragColor = texture2D(tex0, vUv);
} else {
gl_FragColor = vec4(0.5, 0.5, 1.0, 1.0);
}
}
`
}
You have to text the y component of the texture coordinate rather than the x component of the vertex coordinate. The components of the texture coordinates are in range [0.0, 1.0]. Hence divider has to be value in range [0.0, 1.0], too:
vec4 texColor0 = texture2D(tex0, vUv);
vec4 texColor1 = texture2D(tex1, vUv);
vec4 sliderColor = vec4(0.5, 0.5, 1.0, 1.0);
float limit0 = divider - dividerWidth;
float limit1 = divider + dividerWidth;
gl_FragColor = vUv.y > limit1 ? texColor1 : (vUv.y < limit0 ? texColor0 : sliderColor);
I'm having a problem with fragment shader as you can see in the image below.
I don't want to render the parts that are in red in the image
I have to passes which culls clockwise and anticlockwise
and I'm getting the dot product of the normal with the camera position
if its less than 0 I set a transparent fragment
otherwise discard the fargment
here is the shader
#version 100
precision mediump float;
varying float lightDiffuse;
void main()
{
float light = ( 1.0 - lightDiffuse) * 0.5;
vec3 lightColor = vec3(0.0,1.0,1.0);
vec3 diffuseColor = lightColor * light ;
vec4 c;
if(lightDiffuse <0.0 )
{
// back faces, opaque
// front faces, very transparent
c = vec4(diffuseColor, 0.2);
}
else
{
discard;
}
gl_FragColor = c;
}
#version 100
#define lowp
#define mediump
#define highp
attribute vec4 vertex;
attribute vec3 normal;
uniform mat4 normalMatrix;
uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelView;
uniform vec3 camera_world_position;
varying highp float lightDiffuse;
void main()
{
gl_Position = modelViewProjectionMatrix * vertex;
vec3 norm = normal;
norm *=-1.0;
lightDiffuse = dot(normalize(vec3(norm.x, norm.y, norm.z)), normalize(camera_world_position));
}
here is the material script
material 44267_1508405690_0##carpaint
{
technique
{
pass
{
cull_hardware anticlockwise
scene_blend alpha_blend
vertex_program_ref char_shader2_vs100
{
param_named_auto modelViewProjectionMatrix worldviewproj_matrix
param_named_auto normalMatrix inverse_transpose_world_matrix
param_named_auto modelView worldview_matrix
param_named_auto camera_world_position camera_position
}
fragment_program_ref char_shader2_fs100
{
}
}
pass
{
cull_hardware clockwise
vertex_program_ref char_shader2_vs100
{
param_named_auto modelViewProjectionMatrix worldviewproj_matrix
param_named_auto normalMatrix inverse_transpose_world_matrix
param_named_auto modelView worldview_matrix
param_named_auto camera_world_position camera_position
}
fragment_program_ref char_shader2_fs100
{
}
}
}
}
If you want to cull occluded triangles, allocate a depth buffer and use a depth test, it's what it exists for.
Don't do facing tests in the fragment shader, that's not necessary and horribly expensive, just enable GL_CULL_FACE and set the front face correctly. Note that not all models downloaded off the internet get this right, so you might have an input model with broken winding for some triangles.
I want to see a wireframe of an object without the diagonals like
Currently, I add lines according to the vertices, the problem is after I have several of those I experience a major performance degradation.
The examples here are either too new for my version of Three or don't work (I commented there about it).
So I want to try to implement a shader instead.
I tried to use this shader: https://stackoverflow.com/a/31610464/4279201 but it breaks the shape to parts and I'm getting WebGL errors.
That's how I use it:
const vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`
const fragmentShader = `
#version 150 compatibility
flat in float diffuse;
flat in float specular;
flat in vec3 edge_mask;
in vec2 bary;
uniform float mesh_width = 1.0;
uniform vec3 mesh_color = vec3(0.0, 0.0, 0.0);
uniform bool lighting = true;
out vec4 frag_color ;
float edge_factor(){
vec3 bary3 = vec3(bary.x, bary.y, 1.0 - bary.x - bary.y);
vec3 d = fwidth(bary3);
vec3 a3 = smoothstep(vec3(0.0, 0.0, 0.0), d * mesh_width, bary3);
a3 = vec3(1.0, 1.0, 1.0) - edge_mask + edge_mask * a3;
return min(min(a3.x, a3.y), a3.z);
}
void main() {
float s = (lighting && gl_FrontFacing) ? 1.0 : -1.0;
vec4 Kdiff = gl_FrontFacing ?
gl_FrontMaterial.diffuse : gl_BackMaterial.diffuse;
float sdiffuse = s * diffuse;
vec4 result = vec4(0.1, 0.1, 0.1, 1.0);
if (sdiffuse > 0.0) {
result += sdiffuse * Kdiff +
specular * gl_FrontMaterial.specular;
}
frag_color = (mesh_width != 0.0) ?
mix(vec4(mesh_color, 1.0), result, edge_factor()) :
result;
}`
...
const uniforms = {
color: {
value: new THREE.Vector4(0, 0, 1, 1),
type: 'v4'
}
}
const material = new THREE.ShaderMaterial({
fragmentShader: data.fragmentShader,
vertexShader: data.vertexShader,
uniforms
})
this._viewer.impl.matman().addMaterial(
data.name, material, true)
const fragList = this._viewer.model.getFragmentList()
this.toArray(fragIds).forEach((fragId) => {
fragList.setMaterial(fragId, material)
})
So to implement this shader, is the right approach would be to basically check the angle between every two vertices, and draw a line if the degree is 90?
How can I have access to all the vertices of the shape from the vertex shader?
And how can I tell the fragment shader to draw a line between two vertices that match the above condition? (also to leave the default shading for everything else as is)
I'm using Autodesk viewer that uses Three.js rev 71.
// -- Vertex Shader --
precision mediump float;
// Input from buffers
attribute vec3 aPosition;
attribute vec2 aBaryCoord;
// Value interpolated accross pixels and passed to the fragment shader
varying vec2 vBaryCoord;
// Uniforms
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjMatrix;
void main() {
vBaryCoord = aBaryCoord;
gl_Position = uProjMatrix * uViewMatrix * uModelMatrix * vec4(aPosition,1.0);
}
// ---------------------
// -- Fragment Shader --
// This shader doesn't perform any lighting
precision mediump float;
varying vec2 vBaryCoord;
uniform vec3 uMeshColour;
float edgeFactor() {
vec3 d = fwidth(vBaryCoord);
vec3 a3 = smoothstep(vec3(0.0,0.0,0.0),d * 1.5,vBaryCoord);
return min(min(a3.x,a3.y),a3.z);
}
void main() {
gl_FragColor = vec4(uMeshColour,(1.0 - edgeFactor()) * 0.95);
}
// ---------------------
/*
This code isn't tested so take it with a grain of salt
Idea taken from
http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/
*/
I have a simple shader in my Three.js application that colors the screen red. However, I want to color all pixels to the right of a given world position to to a different color.
I have seen some answers that suggest using varying vec4 worldCoord = gl_ModelViewMatrix * gl_Vertex;, but since WebGL using GLSLES, variables like gl_Vertex are not available to me.
Vertex Shader
<script type="x-shader/x-vertex" id="vertexshader">
#ifdef GL_ES
precision highp float;
#endif
void main()
{
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
</script>
Fragment Shader
<script type="x-shader/x-fragment" id="fragmentshader">
#ifdef GL_ES
precision highp float;
#endif
float worldX = 10.0; //Or some other position in the WebGL world
void main()
{
if(gl_FragCoord.x > worldX) //FragCoord gives me coordinates relative to the screen
{
gl_FragColor = vec4(0.0, 1.0, 0.0, 1);
}
else
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1);
}
}
</script>
Q: How do I convert the position of a pixel to it's world position in WebGL using Three.js?
Answer derived from WestLangley's Fiddle here: http://jsfiddle.net/ST4aM/2/.
Vertex Shader
<script type="x-shader/x-vertex" id="vertexshader">
#ifdef GL_ES
precision highp float;
#endif
varying float x;
varying float y;
void main()
{
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
x = position.x;
y = position.y;
}
</script>
Fragment Shader
<script type="x-shader/x-fragment" id="fragmentshader">
#ifdef GL_ES
precision highp float;
#endif
varying float x;
varying float y;
void main()
{
if(x > somePosition)
{
gl_FragColor = vec4(0.0, 1.0, 0.0, 1);
}
else
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1);
}
}
</script>