Is it possible to use THREE.Water in combination with my own texture? Or does anyone have another suggestion how I could make it look a bit more cartoony?
THREE.Water
and THREE.Water2
are not intended to use external maps. If you study the details of the implementation, you will see that both objects reflect the actual environment on the water surface in realtime. THREE.Water2
also supports refraction so objects under the water surface are actually visible. An additional map does not fit in this concept.
If you need a more cartoonish look and feel, I suggest you use a totally different implementation which is less expensive. Just google for “toon shading water” and you will find many interesting tutorials about that topic.
…working on it, but can’t get my head around something. Considder this image:
In the front you see some plants. They are textures with transparency on some faces. Behind is the water (greenish stuff). As you can see, the texture transparency works for every other scene element but the water.
Can anyone tell me why it is blocking my custom shader water? I use ShaderMaterial with the Phong-lib as a basis. I only made some changes in the vertex-shader, but no changes in the fragment-shader.
this is the code where I build up the ShaderMaterial:
var wVertex=THREE.ShaderLib[baseShader].vertexShader;
var wFragment=THREE.ShaderLib[baseShader].fragmentShader;
wVertex=`
uniform float time;
uniform float scale;
uniform float waveX;
uniform float waveZ;
`+wVertex;
wVertex=wVertex.replace('#include <project_vertex>',
`
transformed.y+= (cos(transformed.z * waveZ + time) * sin(transformed.x * 1.0 + waveX))*scale;
vNormal.x+= sin(transformed.x * waveX + time) * scale;
vNormal.y+= cos(transformed.z * waveZ + time) * scale;
vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );
gl_Position = projectionMatrix * mvPosition;
`);
var wUniforms = THREE.UniformsUtils.merge([
THREE.ShaderLib[baseShader].uniforms,
{ time: { value: 1.0 } },
{ scale: { value: 0.3 } },
{ speed: { value: 1 } },
{ waveX: { value: 2.0 } },
{ waveZ: { value: 2.0 } }
]);
var material = new THREE.ShaderMaterial( {
uniforms: wUniforms,
vertexShader: wVertex,
fragmentShader: wFragment,
lights: true,
name: 'custom-material',
transparent: true,
} );
While navigating my scene I noticed two other cases in which the transparent part blocks other objects:
- other parts of the plant (yellow arrow)
- OutlineEffect-edges
Both are cases of special shaders. The plants have a custom shader because of instancing. It also is basic phong with only a modification to the vertex shader.
The outlineEffect also uses a non-standard shader.
Strange thing here is, that the plant leafs are not always blocking other plant leafs (blue arrow). I somehow think there might be an issue with the render order or depth buffer of ShaderMaterials.
Instead of making the plants transparent how about render them as opaque objects with Material.alphaTest
set to a value like 0.5
.
Using AlphaTest with any other value but 0 gives one side black where it should be transparent:
This is with .side=THREE.DoubleSide
When I set .side to either back or front, the texture only shows up on one side - as could be expected.
…when I increase the renderOrder property, the water behind the plants will be rendered. But there still are issues with transparent parts blocking other parts of plants.
I have a strong feeling I need to influence the way the depth-buffer is filled. Am I right to assume I need to write a custom DepthBuffer? This is what I found in the documentation:
.customDepthMaterial : Material
Custom depth material to be used when rendering to the depth map. Can only be used in context of meshes. When shadow-casting with a DirectionalLight or SpotLight, if you are (a) modifying vertex positions in the vertex shader, (b) using a displacement map, (c) using an alpha map with alphaTest, or (d) using a transparent texture with alphaTest, you must specify a customDepthMaterial for proper shadows. Default is undefined .
I think I should write a DepthMaterial shader that just does not write depth for the transparent parts. That might be it… please correct me if I am on the wrong track. In Dutch we say it is better to turn around half way than get lost all the way…
I am afraid the custom depth material does not remove the black side of the leafs.
Let’s see where we are now:
problem: when using a double sided face with a texture with transparency, there are three main issues,
- one face, presumably the back face, is black
- the transparent parts are blocking out my custom shader water. Normal parts are not blocked
- the transparent parts also block other parts of the same object.
Possible solutions tested:
- using alphaTest=0.5
- renderOrder=100 (and the rest is default 0)
- adding custom DepthShader with alphaTest=0.5 in combination with solution 1
Results:
Starting situation: alphaTest=0, transparent=true > problems 2 + 3 (problem 1 does not appear)
Solution 1: alphaTest=0.5 > 2+3 seem to be solved, 1 now appears
Solution 2: renderOrder=100 > 2 is solved, problem 1 is not appearant, but problem 3 is very much there.
Solution 3: custom depth shader > can’t really see a difference with solution 1. The black side is there.
So I think the remaining problem now is what is this black side and how to get rid of it.
One last point: when I switch of depthTest, the dark back is gone, but my scene is messed up since the plants are drawn over everything else.
GOT IT…
Again it was a side effect of the OutlineEffect. When I turned that off, the plants were transparent on both sides. Luckily you can switch it on or off for every material, so I do not need to remove it entirely - I keep coming back to this: I really do love the OutlineEffect but it is giving me so much headache.