-
Notifications
You must be signed in to change notification settings - Fork 235
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
Normals are not rendered correctly #39
Comments
Ok, I figured out that I need to supply the You might want to change the default for that since most users probably don't want to have their model smoothened. |
@marian42, may I ask how to get normal image using pyrender? Thanks. |
Are you looking for a normal buffer of the rendered frame? |
Thanks for your reply @marian42. Both normal buffer and normal map. |
I recently had to generate a normal buffer with pyrender, so here is what I did: Define a custom vertex shader in #version 330 core
// Vertex Attributes
layout(location = 0) in vec3 position;
layout(location = NORMAL_LOC) in vec3 normal;
layout(location = INST_M_LOC) in mat4 inst_m;
// Uniforms
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
// Outputs
out vec3 frag_position;
out vec3 frag_normal;
void main()
{
gl_Position = P * V * M * inst_m * vec4(position, 1);
frag_position = vec3(M * inst_m * vec4(position, 1.0));
mat4 N = transpose(inverse(M * inst_m));
frag_normal = normalize(vec3(N * vec4(normal, 0.0)));
} Define a custom fragment shader in #version 330 core
in vec3 frag_position;
in vec3 frag_normal;
out vec4 frag_color;
void main()
{
vec3 normal = normalize(frag_normal);
frag_color = vec4(normal * 0.5 + 0.5, 1.0);
} Now you can generate a normal buffer like this: import trimesh
import pyrender
import numpy as np
from PIL import Image
class CustomShaderCache():
def __init__(self):
self.program = None
def get_program(self, vertex_shader, fragment_shader, geometry_shader=None, defines=None):
if self.program is None:
self.program = pyrender.shader_program.ShaderProgram("shaders/mesh.vert", "shaders/mesh.frag", defines=defines)
return self.program
camera_pose = np.array(
[[ 1, 0, 0, 0],
[ 0, 0, -1, -4],
[ 0, 1, 0, 0],
[ 0, 0, 0, 1]]
)
scene = pyrender.Scene(bg_color=(0, 0, 0))
scene.add(pyrender.Mesh.from_trimesh(trimesh.primitives.Capsule(), smooth = False))
camera = pyrender.PerspectiveCamera(yfov=np.pi / 3.0, aspectRatio=1.0, znear = 0.5, zfar = 40)
scene.add(camera, pose=camera_pose)
renderer = pyrender.OffscreenRenderer(512, 512)
renderer._renderer._program_cache = CustomShaderCache()
normals, depth = renderer.render(scene)
world_space_normals = normals / 255 * 2 - 1
image = Image.fromarray(normals, 'RGB')
image.show() Now if you want a normal buffer it might be useful to disable antialiasing. To do that, I changed # Clear it
glClearColor(*scene.bg_color)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glDisable(GL_MULTISAMPLE) ###### change here
# .....
# Generate multisample buffer
self._main_cb_ms, self._main_db_ms = glGenRenderbuffers(2)
glBindRenderbuffer(GL_RENDERBUFFER, self._main_cb_ms)
glRenderbufferStorage( ###### change here
GL_RENDERBUFFER, GL_RGBA, ###### change here
self.viewport_width, self.viewport_height
)
glBindRenderbuffer(GL_RENDERBUFFER, self._main_db_ms)
glRenderbufferStorage( ###### change here
GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, ###### change here
self.viewport_width, self.viewport_height
) Maybe @mmatl could add an option to pyrender to disable antialiasing. |
I'll have a try. Thank you very much for help @marian42. |
@LittleYuer map points to it's norms, and then render color image |
Thanks for your detailed description @marian42 ! Works like a charm |
One more addition: if you're on Mac, you'll also need to change this in # Resize for macos if needed
if sys.platform == 'darwin':
color_im = self._resize_image(color_im, False) # Change last parameter (anti-alias) to False. |
This is a very helpful thread. This is the second time I am referring to this thread, this time for a different project. It will be very useful if the developers can bring this as a feature. Maybe we can add a RenderFlag called "DISABLE_ANTI_ALIASING" and then use that to condition multi-sample in a render call. (E,g,: #175). But, this mechanism cannot handle the macOS specific cases mentioned above by @ndahlquist. |
Thanks for your scripts @marian42 ! Would you pls tell me the coordinate of your output normal map? world space or camera space? |
…change other calls of _resize_image for MacOS, similar to the PR linked to this commit Similar to LeiaInc@f933ba1 mmatl#39
Thanks @marian42, still works out of the box! One small addition: The import pyrender
from pyrender.shader_program import ShaderProgramCache
renderer = pyrender.OffscreenRenderer(640, 480)
renderer._renderer._program_cache = ShaderProgramCache(shader_dir="shaders") |
I cannot compile the shader: Any ideas? |
Using the simple offscreen rendering example, my models have incorrect normals (see screenshot on the right).
If I display the mesh with trimesh's
mesh.show()
, it looks correct (left part of the screenshot).This happens with all models that I tested and even if I supply a mesh without normals.
The text was updated successfully, but these errors were encountered: