/* * Fragment shader for surface color based on surface normals. */ static void fragment_shader_color(int y, int x, struct fragment_input *input, struct uniform_variables *vars){ if(input->frag_coord[VAR_Z] >= read_depth(y, x)){ return; } vec3 object_normal; object_normal[VAR_X] = input->attributes[0] / input->frag_coord[VAR_W]; object_normal[VAR_Y] = input->attributes[1] / input->frag_coord[VAR_W]; object_normal[VAR_Z] = input->attributes[2] / input->frag_coord[VAR_W]; normalize_vec3(object_normal); if(input->front_facing == ER_FALSE){ object_normal[VAR_X] = -object_normal[VAR_X]; object_normal[VAR_Y] = -object_normal[VAR_Y]; object_normal[VAR_Z] = -object_normal[VAR_Z]; } float red, green, blue; red = (object_normal[VAR_X] * 0.5f + 0.5f); red = clamp(red, 0.0f, 1.0f); green = (object_normal[VAR_Y] * 0.5f + 0.5f); green = clamp(green, 0.0f, 1.0f); blue = (object_normal[VAR_X] * 0.5f + 0.5f); blue = clamp(blue, 0.0f, 1.0f); write_color(y, x, red, green, blue, 1.0f); write_depth(y, x, input->frag_coord[VAR_Z]); }
/* * Fragment shader for axis and arrows. */ static void fragment_shader_axis(int y, int x, struct fragment_input *input, struct uniform_variables *vars){ if(input->frag_coord[VAR_Z] >= read_depth(y, x)){ return; } write_color(y, x, input->attributes[0], input->attributes[1], input->attributes[2], 1.0f); write_depth(y, x, input->frag_coord[VAR_Z]); }
boost::optional<Eigen::Vector3f> read_depth_and_unproject(const Vector2i &screen_pos, const Eigen::Matrix4f &model, const Eigen::Matrix4f &proj, const Vector2i &viewportSize, bool flipY) { float z = read_depth(screen_pos, flipY, viewportSize.y()); if (z == 1.0f) return boost::none; return unproject(Eigen::Vector3f{(float)screen_pos.x(), (float)screen_pos.y(), z}, model, proj, viewportSize, flipY); }
static void find_actual_mrd(GLdouble *next_to_near, GLdouble *next_to_far, GLdouble *actual_mrd_near, GLdouble *actual_mrd_far) { /* Here we use polygon offset to determine the implementation's actual * MRD. */ double base_depth; glDepthFunc(GL_ALWAYS); /* Draw a quad far away from the eye and read the depth at its * center: */ glDisable(GL_POLYGON_OFFSET_FILL); draw_quad_at_distance(*next_to_far); base_depth = read_depth(piglit_width/2, piglit_height/2); /* Now draw a quad that's one MRD closer to the eye: */ glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(0.0, -1.0); draw_quad_at_distance(*next_to_far); /* The difference between the depths of the two quads is the value the * implementation is actually using for one MRD: */ *actual_mrd_far = base_depth - read_depth(piglit_width/2, piglit_height/2); /* Repeat the process for a quad close to the eye: */ glDisable(GL_POLYGON_OFFSET_FILL); draw_quad_at_distance(*next_to_near); base_depth = read_depth(piglit_width / 2, piglit_height / 2); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(0.0, 1.0); /* 1 MRD further away */ draw_quad_at_distance(*next_to_near); *actual_mrd_near = read_depth(piglit_width / 2, piglit_height / 2) - base_depth; }
/* * Fragment shader for surface lighting. One directional light source, phong shading. */ static void fragment_shader_light(int y, int x, struct fragment_input *input, struct uniform_variables *vars){ if(input->frag_coord[VAR_Z] >= read_depth(y, x)){ return; } float *light_dir = &(vars->uniform_float[0]); vec3 eye_normal, object_normal; object_normal[VAR_X] = input->attributes[0] / input->frag_coord[VAR_W]; object_normal[VAR_Y] = input->attributes[1] / input->frag_coord[VAR_W]; object_normal[VAR_Z] = input->attributes[2] / input->frag_coord[VAR_W]; eye_normal[VAR_X] = input->attributes[3] / input->frag_coord[VAR_W]; eye_normal[VAR_Y] = input->attributes[4] / input->frag_coord[VAR_W]; eye_normal[VAR_Z] = input->attributes[5] / input->frag_coord[VAR_W]; normalize_vec3(eye_normal); normalize_vec3(object_normal); if(input->front_facing == ER_FALSE){ eye_normal[VAR_X] = -eye_normal[VAR_X]; eye_normal[VAR_Y] = -eye_normal[VAR_Y]; eye_normal[VAR_Z] = -eye_normal[VAR_Z]; object_normal[VAR_X] = -object_normal[VAR_X]; object_normal[VAR_Y] = -object_normal[VAR_Y]; object_normal[VAR_Z] = -object_normal[VAR_Z]; } float diffuse_term = max(0.0f, dot_vec3(light_dir, eye_normal) ); float specular_term = 0.0f; vec3 view_vector; vec3 half_vector; view_vector[VAR_X] = 0.0f; view_vector[VAR_Y] = 0.0f; view_vector[VAR_Z] = 1.0f; if(diffuse_term > 0.0f){ half_vector[VAR_X] = light_dir[VAR_X] + view_vector[VAR_X]; half_vector[VAR_Y] = light_dir[VAR_Y] + view_vector[VAR_Y]; half_vector[VAR_Z] = light_dir[VAR_Z] + view_vector[VAR_Z]; normalize_vec3(half_vector); specular_term = pow( max(0.0f, dot_vec3(half_vector, eye_normal)), 50.0f ); } float red, green, blue, light_intensity; light_intensity = 0.6f * diffuse_term + 0.4f * specular_term; red = (object_normal[VAR_X] * 0.5f + 0.5f) * light_intensity; red = clamp(red, 0.0f, 1.0f); green = (object_normal[VAR_Y] * 0.5f + 0.5f) * light_intensity; green = clamp(green, 0.0f, 1.0f); blue = (object_normal[VAR_Z] * 0.5f + 0.5f) * light_intensity; blue = clamp(blue, 0.0f, 1.0f); write_color(y, x, red, green, blue, 1.0f); write_depth(y, x, input->frag_coord[VAR_Z]); }
/* * Fragment shader for texture mapped cube. */ static void fs_cube(int y, int x, struct fragment_input *input, struct uniform_variables *vars){ if(input->frag_coord[VAR_Z] >= read_depth(y, x)){ return; } struct texture* tex = vars->uniform_texture[0]; vec2 tex_coord; vec4 tex_color; tex_coord[VAR_S] = input->attributes[0] / input->frag_coord[VAR_W]; tex_coord[VAR_T] = input->attributes[1] / input->frag_coord[VAR_W]; texture_lod(tex, tex_coord, 0.0f, tex_color); write_color(y, x, tex_color[0], tex_color[1], tex_color[2], 1.0f); write_depth(y, x, input->frag_coord[VAR_Z]); }
/* * Fragment shader for texture mapped cube. Calculation of perspective correct derivatives for trilinear filtering. */ static void fs_cube_grad(int y, int x, struct fragment_input *input, struct uniform_variables *vars){ if(input->frag_coord[VAR_Z] >= read_depth(y, x)){ return; } struct texture *tex = vars->uniform_texture[0]; vec2 tex_coord; vec4 tex_color; tex_coord[VAR_S] = input->attributes[0] / input->frag_coord[VAR_W]; tex_coord[VAR_T] = input->attributes[1] / input->frag_coord[VAR_W]; vec2 ddx, ddy; float one_over_w2 = 1.0f / (input->frag_coord[VAR_W] * input->frag_coord[VAR_W]); ddx[VAR_S] = (input->ddx[0] * input->frag_coord[VAR_W] - input->attributes[0] * input->dw_dx) * one_over_w2; ddx[VAR_T] = (input->ddx[1] * input->frag_coord[VAR_W] - input->attributes[1] * input->dw_dx) * one_over_w2; ddy[VAR_S] = (input->ddy[0] * input->frag_coord[VAR_W] - input->attributes[0] * input->dw_dy) * one_over_w2; ddy[VAR_T] = (input->ddy[1] * input->frag_coord[VAR_W] - input->attributes[1] * input->dw_dy) * one_over_w2; texture_grad(tex, tex_coord, ddx, ddy, tex_color); write_color(y, x, tex_color[0], tex_color[1], tex_color[2], 1.0f); write_depth(y, x, input->frag_coord[VAR_Z]); }
static bool check_slope_offset(const struct angle_axis *aa, GLdouble *ideal_mrd_near) { /* This function checks for correct slope-based offsets for a quad * rotated to a given angle around a given axis. * * The basic strategy is to: * Draw the quad. (Note: the quad's size and position * are chosen so that it won't ever be clipped.) * Sample three points in the quad's interior. * Compute dz/dx and dz/dy based on those samples. * Compute the range of allowable offsets; must be between * max(abs(dz/dx), abs(dz/dy)) and * sqrt((dz/dx)**2, (dz/dy)**2) * Sample the depth of the quad at its center. * Use PolygonOffset to produce an offset equal to one * times the depth slope of the base quad. * Draw another quad with the same orientation as the first. * Sample the second quad at its center. * Compute the difference in depths between the first quad * and the second. * Verify that the difference is within the allowable range. * Repeat for a third quad at twice the offset from the first. * (This verifies that the implementation is scaling * the depth offset correctly.) */ const GLfloat quad_dist = 2.5; /* must be > 1+sqrt(2) to avoid */ /* clipping by the near plane */ GLdouble modelview_mat[16]; GLdouble projection_mat[16]; GLint viewport[4]; GLdouble centerw[3]; GLdouble base_depth; GLdouble p0[3]; GLdouble p1[3]; GLdouble p2[3]; double det, dzdx, dzdy, mmax, mmin; GLdouble offset_depth, offset; glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glColor3f(1.0, 0.0, 0.0); /* red */ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -quad_dist); glRotatef(aa->angle, aa->axis[0], aa->axis[1], aa->axis[2]); glGetDoublev(GL_MODELVIEW_MATRIX, modelview_mat); glGetDoublev(GL_PROJECTION_MATRIX, projection_mat); glGetIntegerv(GL_VIEWPORT, viewport); glDisable(GL_POLYGON_OFFSET_FILL); piglit_draw_rect(-1.0, -1.0, 2.0, 2.0); project(0.0, 0.0, 0.0, modelview_mat, projection_mat, viewport, centerw); base_depth = read_depth(centerw[0], centerw[1]); project(-0.9, -0.9, 0.0, modelview_mat, projection_mat, viewport, p0); p0[2] = read_depth(p0[0], p0[1]); project( 0.9, -0.9, 0.0, modelview_mat, projection_mat, viewport, p1); p1[2] = read_depth(p1[0], p1[1]); project( 0.9, 0.9, 0.0, modelview_mat, projection_mat, viewport, p2); p2[2] = read_depth(p2[0], p2[1]); det = (p0[0] - p1[0]) * (p0[1] - p2[1]) - (p0[0] - p2[0]) * (p0[1] - p1[1]); if (fabs(det) < 0.001) return false; /* too close to colinear to evaluate */ dzdx = ((p0[2] - p1[2]) * (p0[1] - p2[1]) - (p0[2] - p2[2]) * (p0[1] - p1[1])) / det; dzdy = ((p0[0] - p1[0]) * (p0[2] - p2[2]) - (p0[0] - p2[0]) * (p0[2] - p1[2])) / det; mmax = 1.1 * sqrt(dzdx * dzdx + dzdy * dzdy) + (*ideal_mrd_near); /* (adding ideal_mrd_near is a fudge for roundoff error */ /* when the slope is extremely close to zero) */ mmin = 0.9 * fmax(fabs(dzdx), fabs(dzdy)); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0, 0.0); piglit_present_results(); piglit_draw_rect(-1.0, -1.0, 2.0, 2.0); offset_depth = read_depth(centerw[0], centerw[1]); offset = fmax(base_depth - offset_depth, 0.0); if (offset < mmin || offset > mmax) { if (offset < mmin) printf("Depth-slope related offset was too small"); else printf("Depth-slope related offset was too large"); printf("; first failure at:\n"); printf("\tAngle = %f degrees, axis = (%f, %f, %f)\n", aa->angle, aa->axis[0], aa->axis[1], aa->axis[2]); printf("\tFailing offset was %.16f\n", offset); printf("\tAllowable range is (%f, %f)\n", mmin, mmax); return false; } glPolygonOffset(-2.0, 0.0); piglit_present_results(); piglit_draw_rect(-1.0, -1.0, 2.0, 2.0); offset_depth = read_depth(centerw[0], centerw[1]); offset = fmax(base_depth - offset_depth, 0.0); if (offset < 2.0 * mmin || offset > 2.0 * mmax) { if (offset < 2.0 * mmin) printf("Depth-slope related offset was too small"); else printf("Depth-slope related offset was too large"); printf("; first failure at:\n"); printf("\tAngle = %f degrees, axis = (%f, %f, %f)\n", aa->angle, aa->axis[0], aa->axis[1], aa->axis[2]); printf("\tFailing offset was %.16f\n", offset); printf("\tAllowable range is (%f, %f)\n", 2.0 * mmin, 2.0 * mmax); return false; } return true; }