Beispiel #1
0
// render the scene with OpenGL
void shade(Scene* scene, ShadeState* state) {
    // enable depth test
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    // disable culling face
    glDisable(GL_CULL_FACE);

    // let the shader control the points
    glEnable(GL_POINT_SPRITE);
    
    // set up the viewport from the scene image size
    glViewport(0, 0, scene->image_width, scene->image_height);
    
    // clear the screen (both color and depth) - set cleared color to background
    glClearColor(scene->background.x, scene->background.y, scene->background.z, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    // enable program
    glUseProgram(state->gl_program_id);
    
    // bind camera's position, inverse of frame and projection
    // use frame_to_matrix_inverse and frustum_matrix
    glUniform3fv(glGetUniformLocation(state->gl_program_id,"camera_pos"),
                 1, &scene->camera->frame.o.x);
    glUniformMatrix4fv(glGetUniformLocation(state->gl_program_id,"camera_frame_inverse"),
                       1, true, &frame_to_matrix_inverse(scene->camera->frame)[0][0]);
    glUniformMatrix4fv(glGetUniformLocation(state->gl_program_id,"camera_projection"),
                       1, true, &frustum_matrix(-scene->camera->dist*scene->camera->width/2, scene->camera->dist*scene->camera->width/2,
                                                -scene->camera->dist*scene->camera->height/2, scene->camera->dist*scene->camera->height/2,
                                                scene->camera->dist,10000)[0][0]);
    
    // bind ambient and number of lights
    glUniform3fv(glGetUniformLocation(state->gl_program_id,"ambient"),1,&scene->ambient.x);
    glUniform1i(glGetUniformLocation(state->gl_program_id,"lights_num"),scene->lights.size());
    
    // foreach light
    auto count = 0;
    for(auto light : scene->lights) {
        // bind light position and internsity (create param name with tostring)
        glUniform3fv(glGetUniformLocation(state->gl_program_id,tostring("light_pos[%d]",count).c_str()),
                     1, &light->frame.o.x);
        glUniform3fv(glGetUniformLocation(state->gl_program_id,tostring("light_intensity[%d]",count).c_str()),
                     1, &light->intensity.x);
        count++;
    }
    
    // foreach mesh
    for(auto mesh : scene->meshes) {
        // bind material kd, ks, n
        glUniform3fv(glGetUniformLocation(state->gl_program_id,"material_kd"),
                     1,&mesh->mat->kd.x);
        glUniform3fv(glGetUniformLocation(state->gl_program_id,"material_ks"),
                     1,&mesh->mat->ks.x);
        glUniform1f(glGetUniformLocation(state->gl_program_id,"material_n"),
                    mesh->mat->n);

        // YOUR CODE GOES HERE ---------------------
        // bind texture params (txt_on, sampler)
		_bind_texture("material_kd_txt", "material_kd_txt_on", mesh->mat->kd_txt, 0, state);
		_bind_texture("material_ks_txt", "material_ks_txt_on", mesh->mat->ks_txt, 1, state);
		_bind_texture("material_norm_txt", "material_norm_txt_on", mesh->mat->norm_txt, 2, state);

        // bind mesh frame - use frame_to_matrix
        glUniformMatrix4fv(glGetUniformLocation(state->gl_program_id,"mesh_frame"),
                           1,true,&frame_to_matrix(mesh->frame)[0][0]);
    
        // enable vertex attributes arrays and set up pointers to the mesh data
        auto vertex_pos_location = glGetAttribLocation(state->gl_program_id, "vertex_pos");
        auto vertex_norm_location = glGetAttribLocation(state->gl_program_id, "vertex_norm");

        // YOUR CODE GOES HERE ---------------------
		auto vertex_texcoord_location = glGetAttribLocation(state->gl_program_id, "vertex_texcoord");

        glEnableVertexAttribArray(vertex_pos_location);
        glVertexAttribPointer(vertex_pos_location, 3, GL_FLOAT, GL_FALSE, 0, &mesh->pos[0].x);
        glEnableVertexAttribArray(vertex_norm_location);
        glVertexAttribPointer(vertex_norm_location, 3, GL_FLOAT, GL_FALSE, 0, &mesh->norm[0].x);

		// YOUR CODE GOES HERE ---------------------
		if (!mesh->texcoord.empty())
		{

			glEnableVertexAttribArray(vertex_texcoord_location);
			glVertexAttribPointer(vertex_texcoord_location, 2, GL_FLOAT, GL_FALSE, 0, &mesh->texcoord[0].x);
		}
        
        // draw triangles and quads
        if(! scene->draw_wireframe) {
            if(mesh->triangle.size()) glDrawElements(GL_TRIANGLES, mesh->triangle.size()*3, GL_UNSIGNED_INT, &mesh->triangle[0].x);
            if(mesh->quad.size()) glDrawElements(GL_QUADS, mesh->quad.size()*4, GL_UNSIGNED_INT, &mesh->quad[0].x);
        } else {
            auto edges = EdgeMap(mesh->triangle, mesh->quad).edges();
            glDrawElements(GL_LINES, edges.size()*2, GL_UNSIGNED_INT, &edges[0].x);
        }
        
        // draw line sets
        if(! mesh->line.empty()) glDrawElements(GL_LINES, mesh->line.size()*2, GL_UNSIGNED_INT, mesh->line.data());
        for(auto segment : mesh->spline) glDrawElements(GL_LINE_STRIP, 4, GL_UNSIGNED_INT, &segment);
        
        // disable vertex attribute arrays
        glDisableVertexAttribArray(vertex_pos_location);
        glDisableVertexAttribArray(vertex_norm_location);

        // YOUR CODE GOES HERE ---------------------
		if (!mesh->texcoord.empty())
			glDisableVertexAttribArray(vertex_texcoord_location);
    }
}
Beispiel #2
0
// shade a mesh
void shade_mesh(Mesh* mesh, int time, bool wireframe, bool skinning_gpu, bool draw_normals, ShadeState* state) {
    // bind material kd, ks, n
    glUniform3fv(glGetUniformLocation(state->gl_program_id,"material_kd"),
                 1,&mesh->mat->kd.x);
    glUniform3fv(glGetUniformLocation(state->gl_program_id,"material_ks"),
                 1,&mesh->mat->ks.x);
    glUniform1f(glGetUniformLocation(state->gl_program_id,"material_n"),
                mesh->mat->n);
    glUniform1i(glGetUniformLocation(state->gl_program_id,"material_is_lines"),
                GL_FALSE);
    glUniform1i(glGetUniformLocation(state->gl_program_id,"material_double_sided"),
                (mesh->mat->double_sided)?GL_TRUE:GL_FALSE);
    // bind texture params (txt_on, sampler)
    _bind_texture("material_kd_txt", "material_kd_txt_on", mesh->mat->kd_txt, 0, state);
    _bind_texture("material_ks_txt", "material_ks_txt_on", mesh->mat->ks_txt, 1, state);
    _bind_texture("material_norm_txt", "material_norm_txt_on", mesh->mat->norm_txt, 2, state);
    
    // bind mesh frame - use frame_to_matrix
    glUniformMatrix4fv(glGetUniformLocation(state->gl_program_id,"mesh_frame"),
                       1,true,&frame_to_matrix(mesh->frame)[0][0]);
    
    // enable vertex attributes arrays and set up pointers to the mesh data
    auto vertex_pos_location = glGetAttribLocation(state->gl_program_id, "vertex_pos");
    auto vertex_norm_location = glGetAttribLocation(state->gl_program_id, "vertex_norm");
    auto vertex_texcoord_location = glGetAttribLocation(state->gl_program_id, "vertex_texcoord");
    // YOUR CODE GOES HERE ---------------------
    // (only for extra credit)
    auto vertex_skin_bone_ids_location = glGetAttribLocation(state->gl_program_id, "vertex_skin_bone_ids");
    auto vertex_skin_bone_weights_location = glGetAttribLocation(state->gl_program_id, "vertex_skin_bone_weights");
    
    glEnableVertexAttribArray(vertex_pos_location);
    glVertexAttribPointer(vertex_pos_location, 3, GL_FLOAT, GL_FALSE, 0, &mesh->pos[0].x);
    glEnableVertexAttribArray(vertex_norm_location);
    glVertexAttribPointer(vertex_norm_location, 3, GL_FLOAT, GL_FALSE, 0, &mesh->norm[0].x);
    if(not mesh->texcoord.empty()) {
        glEnableVertexAttribArray(vertex_texcoord_location);
        glVertexAttribPointer(vertex_texcoord_location, 2, GL_FLOAT, GL_FALSE, 0, &mesh->texcoord[0].x);
    }
    else glVertexAttrib2f(vertex_texcoord_location, 0, 0);
    
    if (mesh->skinning and skinning_gpu) {
        // YOUR CODE GOES HERE ---------------------
        // (only for extra credit)
        glUniform1i(glGetUniformLocation(state->gl_program_id, "skin_enabled"), true);

        glEnableVertexAttribArray(vertex_skin_bone_ids_location);
        glVertexAttribPointer(vertex_skin_bone_ids_location, 4, GL_INT, GL_FALSE, 0, &mesh->skinning->bone_ids[0].x);
        
        glEnableVertexAttribArray(vertex_skin_bone_weights_location);
        glVertexAttribPointer(vertex_skin_bone_weights_location, 4, GL_FLOAT, GL_FALSE, 0, &mesh->skinning->bone_weights[0].x);

        for (int i = 0; i < 48; i++) {
            string name = "skin_bone_xforms["+std::to_string(i)+"]";
            glUniformMatrix4fv(glGetUniformLocation(state->gl_program_id, name.c_str()), 1, GL_TRUE, &mesh->skinning->bone_xforms[time][i][0].x);
        }
        
    } else {
        glUniform1i(glGetUniformLocation(state->gl_program_id,"skin_enabled"),GL_FALSE);
    }
    
    // draw triangles and quads
    if(not wireframe) {
        if(mesh->triangle.size()) glDrawElements(GL_TRIANGLES, mesh->triangle.size()*3, GL_UNSIGNED_INT, &mesh->triangle[0].x);
        if(mesh->quad.size()) glDrawElements(GL_QUADS, mesh->quad.size()*4, GL_UNSIGNED_INT, &mesh->quad[0].x);
        if(mesh->point.size()) glDrawElements(GL_POINTS, mesh->point.size(), GL_UNSIGNED_INT, &mesh->point[0]);
        if(mesh->line.size()) glDrawElements(GL_LINES, mesh->line.size(), GL_UNSIGNED_INT, &mesh->line[0].x);
        for(auto segment : mesh->spline) glDrawElements(GL_LINE_STRIP, 4, GL_UNSIGNED_INT, &segment);
    } else {
        auto edges = EdgeMap(mesh->triangle, mesh->quad).edges();
        glDrawElements(GL_LINES, edges.size()*2, GL_UNSIGNED_INT, &edges[0].x);
    }
    
    // disable vertex attribute arrays
    glDisableVertexAttribArray(vertex_pos_location);
    glDisableVertexAttribArray(vertex_norm_location);
    if(not mesh->texcoord.empty()) glDisableVertexAttribArray(vertex_texcoord_location);
    if(mesh->skinning) {
        // YOUR CODE GOES HERE ---------------------
        // (only for extra credit)
        glDisableVertexAttribArray(vertex_skin_bone_ids_location);
        glDisableVertexAttribArray(vertex_skin_bone_weights_location);
    }
    
    // draw normals if needed
    if(draw_normals) {
        glUniform3fv(glGetUniformLocation(state->gl_program_id,"material_kd"),
                     1,&zero3f.x);
        glUniform3fv(glGetUniformLocation(state->gl_program_id,"material_ks"),
                     1,&zero3f.x);
        glBegin(GL_LINES);
        for(auto i : range(mesh->pos.size())) {
            auto p0 = mesh->pos[i];
            auto p1 = mesh->pos[i] + mesh->norm[i]*0.1;
            glVertexAttrib3fv(0,&p0.x);
            glVertexAttrib3fv(0,&p1.x);
            if(mesh->mat->double_sided) {
                auto p2 = mesh->pos[i] - mesh->norm[i]*0.1;
                glVertexAttrib3fv(0,&p0.x);
                glVertexAttrib3fv(0,&p2.x);
            }
        }
        glEnd();
    }
}