Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request function Render To Depth #13858

Open
osov opened this issue Apr 13, 2018 · 4 comments
Open

Request function Render To Depth #13858

osov opened this issue Apr 13, 2018 · 4 comments

Comments

@osov
Copy link

osov commented Apr 13, 2018

You need a function similar to renderer.render, but with the ability to render it in depth.
Why is not standard use appropriate?

scene.overrideMaterial = overrideMaterial;
renderer.render (scene, camera, ...);
scene.overrideMaterial = null;

due to the fact that using this method for Skin mesh will be drawn a static position, i.e. without animation.

Why is not suitable use:
renderer.render (scene, camera, ...);
because of the fact that some objects have their own CustomDepthMaterial. And also due to the fact that too heavy shader can be, but in the depths it is not needed.

How did I do this? used something between renderer.render and WebGLShadowMap.renderObject, because in WebGLShadowMap.renderObject is implemented exactly as it should be done in WebGLRenderer.
I just do not want to make my edits to it after every update of the engine, so I ask you to do this, I think it will be useful to many, now it is not enough.

@WestLangley
Copy link
Collaborator

Since you know how to implement your feature request, can you file a pull request (PR) and propose a change to the library?

Also, what is your use case? Your use case can provide a compelling reason for implementing the new feature.

A live example can be helpful.

@osov
Copy link
Author

osov commented Apr 13, 2018

Also, what is your use case?

I explained what does not suit the normal method render. I will repeat.

  1. For example, I have a complex shader for an object.
    There is another shader that needs a depth buffer and if I use the render method, it turns out that the heavy shader will work 2 times. But in fact it is not necessary for the buffer of depth, there the simple shader (or in general standard).

  2. For transparent objects - bushes for example, to get the right shadow, you just need to use customDepthMaterial (but as I understand the render method it does not use it, but uses the usual material). I like using customDepthMaterial, so I often use it, and accordingly I do not just use material, but I write light shaders for such cases and include customDepthMaterial.

  3. if I still want to use a convenient method:

scene.overrideMaterial = customDepthMat;
renderer.render (scene, camera, ...);
scene.overrideMaterial = null;

then it has two drawbacks.
3.1 not all objects are suitable for standard material (for example, bushes should be somewhere leaky)
3.2 SkinMesh objects will be fixed, without animation and there will be an incorrect depth buffer.

Since you know how to implement your feature request, can you file a pull request (PR) and propose a change to the library?

Well, I'll try, is not perfectly, its work, and you will check and if arranged, then deposit it into the library.

for WebGLShadowMap:

this.getDepthMaterials = function()
{
    return _depthMaterials;
}

for WebGLRenderer:

this.renderToDepth = function ( scene, camera, renderTarget, forceClear ) {
			if ( ! ( camera && camera.isCamera ) ) {
				console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
				return;
			}
			if ( _isContextLost ) return;
			// reset caching for this frame
			_currentGeometryProgram = '';
			_currentMaterialId = - 1;
			_currentCamera = null;
			// update scene graph
			if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
			// update camera matrices and frustum
			if ( camera.parent === null ) camera.updateMatrixWorld();
			currentRenderState = renderStates.get( scene, camera );
			currentRenderState.init();
			scene.onBeforeRender( _this, scene, camera, renderTarget );
			_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
			_frustum.setFromMatrix( _projScreenMatrix );
			currentRenderList = renderLists.get( scene, camera );
			currentRenderList.init();
			projectObject( scene, camera, _this.sortObjects );
			if ( _this.sortObjects === true )
				currentRenderList.sort();
			//currentRenderState.setupLights( camera );
			if ( this.info.autoReset ) this.info.reset();
			if ( renderTarget === undefined )
				renderTarget = null;
			this.setRenderTarget( renderTarget );
			//
			background.render( currentRenderList, scene, camera, forceClear );
			// render scene
			var opaqueObjects = currentRenderList.opaque;
			var transparentObjects = currentRenderList.transparent;
			var list = [];
			if (opaqueObjects.length)
				list.push(opaqueObjects);
			if (transparentObjects.length)
				list.push(transparentObjects);
			if ( list.length)
			{
				var materialVariants = this.shadowMap.getDepthMaterials();
				var _MorphingFlag = 1;
				var _SkinningFlag = 2;
				for (var j = 0; j < list.length; j++)
				{
					var objects = list[j];
					for ( var i = 0, l = objects.length; i < l; i ++ )
					{
						var renderItem = objects[ i ];
						var object = renderItem.object;
						var geometry = renderItem.geometry;
						var group = renderItem.group;
						var material = object.material;
						var customMaterial = object.customDepthMaterial;
						if ( ! customMaterial )
						{
							var useMorphing = false;
							if ( material.morphTargets )
							{
								if ( geometry && geometry.isBufferGeometry )
								{
									useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
								} else if ( geometry && geometry.isGeometry )
								{
									useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;
								}
							}
							if ( object.isSkinnedMesh && material.skinning === false )
							{
								console.warn( 'THREE.renderToDepth: THREE.SkinnedMesh with material.skinning set to false:', object );
							}
							var useSkinning = object.isSkinnedMesh && material.skinning;
							var variantIndex = 0;
							if ( useMorphing ) variantIndex |= _MorphingFlag;
							if ( useSkinning ) variantIndex |= _SkinningFlag;
							material = materialVariants[ variantIndex ];
						}
						else
						{
							material = customMaterial;
						}
						renderObject( object, scene, camera, geometry, material, group );
					}
				}
			}

@WestLangley
Copy link
Collaborator

So you want to render the scene to a render target and use object.customDepthMaterial if it is defined, and the default object material variant if it is not. Is that correct?

scene.overrideMaterial would not be used at all in this case. Correct?

@osov
Copy link
Author

osov commented Apr 14, 2018

scene.overrideMaterial would not be used at all in this case. Correct?

Yes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants