How can I apply different shader for GraphicsOutput

I’m going to implement SSAO with Panda3D, so I should make depth texture in the process.

I tried to make depth texture by GraphicsOutput (used GraphicsWindow for test in under code), but I don’ t know how to apply different shader to new window.

I thought one way to apply two shader with two models, but it looks like inefficient.

How can I do it?

#include "pandaFramework.h"
#include "pandaSystem.h"
#include "texturePool.h"

int main(int argc, char *argv[])
{
	PandaFramework framework;
	framework.open_framework(argc, argv);
	framework.set_window_title("Title");

	WindowFramework *window = framework.open_window();
	NodePath render = window->get_render();

	NodePath model = window->load_model(render, "models/winged-victory");
	PT(TextureStage) tex0 = new TextureStage("tex0");
	PT(TextureStage) tex1 = new TextureStage("tex1");
	model.set_texture(tex0, TexturePool::load_texture("models/texture"));
	model.set_texture(tex1, TexturePool::load_texture("models/normal"));

	window->setup_trackball();
	window->center_trackball(model);

	PT(Shader) depShader = Shader::load(Shader::SL_GLSL, "shaders/depth.vert", "shaders/depth.frag");
	
	PT(GraphicsWindow) depBuf = window->get_graphics_window(); // ->make_texture_buffer("depBuf", 800, 600);
	PT(Texture) depTex = depBuf->get_texture();
	PT(DisplayRegion) depRegion = depBuf->make_display_region(0.8, 1, 0.8, 1);
	PT(Camera) depCam = new Camera("depCam");
	NodePath depCamNode(depCam);
	depBuf->set_sort(-1);
	depRegion->set_camera(depCamNode);
	depCamNode.reparent_to(window->get_camera_group());

	//PT(TextureStage) tex2 = new TextureStage("tex2");
	//model.set_texture(tex2, depTex);

	PT(Shader) mainShader = Shader::load(Shader::SL_GLSL, "shaders/shader.vert", "shaders/shader.frag");
	render.set_shader(mainShader);
	render.set_shader_input(~);

	framework.main_loop();
	framework.close_framework();

	return 0;
}

You can use the initial state of the camera to set this.

camera->set_initial_state(RenderState::make(ShaderAttrib::make(shader), 1));

Or:

NodePath state_np("");
state_np.set_shader(shader, 1);
camera->set_initial_state(state_np.get_state());

It works well, thanks! :smiley:

Ah… I find one problem on this code.

I think that main window and graphics window will return same pixel’s position, but they didn’t.

/* c++ code */

#include "pandaFramework.h"
#include "pandaSystem.h"

int main(int argc, char *argv[])
{
	PandaFramework framework;
	framework.open_framework(argc, argv);
	framework.set_window_title("?");

	WindowFramework *window = framework.open_window();
	NodePath render = window->get_render();

	NodePath model = window->load_model(render, "models/winged-victory");

	window->setup_trackball();
	window->center_trackball(model);

	PT(Shader) redShader = Shader::load(Shader::SL_GLSL, "shaders/red.vert", "shaders/red.frag");
	PT(Shader) grnShader = Shader::load(Shader::SL_GLSL, "shaders/grn.vert", "shaders/grn.frag");
	
	PT(GraphicsWindow) buf = window->get_graphics_window();
	PT(DisplayRegion) region = buf->make_display_region();
	PT(Camera) cam = new Camera("cam");
	NodePath camNode(cam);
	buf->set_sort(-1);
	region->set_camera(camNode);
	cam->set_initial_state(RenderState::make(ShaderAttrib::make(grnShader), 1));
	camNode.reparent_to(window->get_camera_group());
	
	render.set_shader(redShader);

	framework.main_loop();
	framework.close_framework();

	return 0;
}

/* vert: same for red and green */

#version 130

uniform mat4 p3d_ModelViewProjectionMatrix;

in vec4 p3d_Vertex;

void main()
{
	gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
}

/* red.frag */

#version 130

void main()
{
	gl_FragColor = vec4(1, 0, 0, 1);
}

/* grn.frag */

#version 130

void main()
{
	gl_FragColor = vec4(0, 1, 0, 1);
}

Moreover, if I change render’s shader to grnShader, two window’s pixel positions are exactly same.

Why does it happen?

I’m really just guessing here, and might be totally wrong, but have you tried setting your main cameras lens on your buffer camera? If they have a different FOV for example, you will get different images. So something like that (untested):

cam->set_lens(window->get_camera(0)->get_lens());

It works perfectly!

Thanks for reply :smiley: