- Home /
Camera.RenderWithShader() and GL drawing: possible?
I have a custom renderer that uses GL draw functions to render objects.
While attempting to do some filtering of objects rendered to a camera, using RenderWithShader (layers wouldn’t work for this), I found my custom renderers were not visible, even though I expected them to be.
As a test I configured my custom renderers to use the same exact shader as the one specified in RenderWithShader, and specified null for the tag parameter (to eliminate the filtering as a possible issue).
In my custom renderer, I draw the lines, and specify the material pass to use.
Void OnRenderOject(){
GL.PushMatrix();
GL.LoadProjectionMatrix(Camera.current.projectionMatrix);
Debug.Log("line mat used: "+ lineMaterial.name);
lineMaterial.SetPass(0);
//…. Lines drawn, cleanup performed
}
If render the camera with:
cam.Render()
The debug.Log string, and drawn lines show up. In addition, the lineMaterial.Name in the log-string, matches the Material using the testShader; “TestShaderMaterial”.
If I call
cam.RenderWithShader(testShader,null)
The debug.log string does not show up, (nor obviously, do the lines). However, MeshRenderers in the scene, ARE visible (and as expected: are using the testShader).
Side-note/additional Info:
I realize the docs state that when using RenderWithShader: “The camera will not send OnPreCull, OnPreRender or OnPostRender to attached scripts. Image filters will not be rendered either.” Though in this case, it’s OnRenderObject() that is not being called, is suspect that’s because it is “similar to” OnPostRender().
Other tests: Manually calling the GL drawing code (before OR after RenderWithShader) does not actually affect the camera’s output, even though the debug-logs confirm it IS drawing lines... somewhere. I pass the camera to the GL drawing code, but I only use it to get projection matrixes and stuff.
possibly of interest: I have a renderTexture attached to the camera. That texture is the FINAL output I'm looking for. The camera is just how I'm getting it.
Main Question: How can I get my GL drawings output to that camera, and still use RenderWithShader?
Answer by Bunny83 · May 31, 2016 at 09:47 PM
Well, first of all GL rendering code has no direct relation to a camera unlike actual "renderer" objects. GL rendering code directly renders to the screen buffer.
RenderWithShader conceptionally won't run any custom GL rendering code automatically as custom GL code sets the used rendering pass manually so RenderWithShader has no way to change the shader.
However running the rendering code manually after the camera has rendered it's "normal" scene you should be able to render your GL stuff manually. Keep in mind when rendering stuff manually you have to take care of everything yourself which includes projection and transform / model matrices as well as Viewport settings. Some might be still valid from the last camera rendering, but you shouldn't rely on that.
You also might need to convert the projection matrix with GL.GetGPUProjectionMatrix however i'm not sure about that as the documentation of GL.LoadProjectionMatrix isn't really clear about if it's going to convert the matrix automatically or not.
$$anonymous$$eep in $$anonymous$$d that a camera just consists of the following things:
projection matrix
view matrix (inverse transform i.e world to camera)
an API to "start" rendering Unity's Renderer concept based on the culling mask
When rendering manually you take care of those things yourself. In addition a camera usually clears the buffers before rendering but that depends on the clearFlags. If you want / need to clear them manually you can use GL.Clear or GL.ClearWithSkybox.
Though when you want to render things after a camera you usually don't clear anything.
right on the money, as usual @Bunny83! The lines that were being drawn "somewhere" were simply outside the viewport. I changed/added the following to my GL drawing code, and the manually drawn lines showed up:
DrawLines(Camera cam){
GL.Push$$anonymous$$atrix();
$$anonymous$$atrix4x4 projection=GL.GetGPUProjection$$anonymous$$atrix(cam.projection$$anonymous$$atrix,false); //passing the camera's projection matrix through this function doesn't seem to do anything.
GL.LoadProjection$$anonymous$$atrix(projection);
GL.LoadIdentity();
GL.$$anonymous$$ult$$anonymous$$atrix(transform.localToWorld$$anonymous$$atrix);
GL.$$anonymous$$ult$$anonymous$$atrix(cam.worldToCamera$$anonymous$$atrix);
Debug.Log("drawing lines");
line$$anonymous$$aterial.SetPass(0);
....
Also important to note: I had to call RenderTexture.active = cam.targetTexture; for the lines to show up on the camera's RenderTexture, my final output.
Your answer

Follow this Question
Related Questions
Using a camera replacement shader but keeping the underlying (original) colors? -4 Answers
Rendertype for Unity's non-legacy Image UI 0 Answers
How to create texture from multiple sprite in unity2d? 0 Answers
Dissable lights per camera? 2 Answers
Rendering the same Render Texture differently to separate cameras 0 Answers