opengl模板测试

  • 这里很多源码包括shader都要改变,所以直接用已有代码进行替换
  • 主函数也相应的需要修改类也发生改变了

修改

  • shader类封装着色器绑定函数
//shader封装绑定函数
void Shader::setMat4(const std::string& name, const glm::mat4& mat) const
{
    glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
void Shader::setBool(const std::string& name, bool value) const
{
    glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
// ------------------------------------------------------------------------
void Shader::setInt(const std::string& name, int value) const
{
    glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
// ------------------------------------------------------------------------
void Shader::setFloat(const std::string& name, float value) const
{
    glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
// ------------------------------------------------------------------------
void Shader::setVec2(const std::string& name, const glm::vec2& value) const
{
    glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void Shader::setVec2(const std::string& name, float x, float y) const
{
    glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
}
// ------------------------------------------------------------------------
void Shader::setVec3(const std::string& name, const glm::vec3& value) const
{
    glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void Shader::setVec3(const std::string& name, float x, float y, float z) const
{
    glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
}
// ------------------------------------------------------------------------
void Shader::setVec4(const std::string& name, const glm::vec4& value) const
{
    glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void Shader::setVec4(const std::string& name, float x, float y, float z, float w)
{
    glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
}
// ------------------------------------------------------------------------
void Shader::setMat2(const std::string& name, const glm::mat2& mat) const
{
    glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
// ------------------------------------------------------------------------
void Shader::setMat3(const std::string& name, const glm::mat3& mat) const
{
    glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
		//使用
		modelShader.useShader();
		modelShader.setMat4("projection",projection);
		modelShader.setMat4("view",view);
		modelShader.setVec4("lightPos",cubePositions[1].r,cubePositions[1].g,cubePositions[1].b,1);
		modelShader.setVec3("viewPos",camera.Position.r,camera.Position.g,camera.Position.b);
		modelShader.setVec3("front",camera.Front.r,camera.Front.g,camera.Front.b);
		modelShader.setVec3("lightColor",1.0f,1.0f,1.0f);
		stencilShader.useShader();
		stencilShader.setMat4("projection",projection);
		stencilShader.setMat4("view",view);
  • 封装点击函数(这里要将用到的map等变成修改全局变量)
//封装点击函数
void modelPicking()
{
    if (pickingModelWorldPosition == true)
    {

        glReadPixels((int)winX, 600 - (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
        float x = (2.0f * winX) / 800.0f - 1.0f;
        float y = 1.0f - (2.0f * winY) / 600.0f;
        float z = winZ * 2.0 - 1.0f;
        pickingModelWorldPosition = false;
        //有像素被点中
        if (winZ < 1.0f)
        {
            //float w = (2.0 * near * far) / (far + near - z * (far - near));
            float w = near * far / (near * winZ - far * winZ + far);
            glm::vec4 wolrdPostion = glm::inverse(view) * glm::inverse(projection) * w * glm::vec4(x, y, z, 1);
            //cout<<" x:"<<wolrdPostion.r<<" y:"<<wolrdPostion.g<<" z:"<<wolrdPostion.b<<" w:"<<w<<endl;
            for (_modelsIter = _models.begin(); _modelsIter != _models.end(); _modelsIter++)
            {
                float _distance = glm::distance(_modelsIter->second.first + glm::vec3(0, 7.5, 0), glm::vec3(wolrdPostion));
                if (_distance < 7.5)
                {
                    modelSelected = _modelsIter->first;
                    cout << _modelsIter->first << "模型被选中..." << endl;
                }

            }
        }
        else
        {
            modelSelected = "NULL";
            //cout<<"没有点中模型...."<<endl;
        }

    }
}
  • main函数修改(绘画部分修改)
  • draw区分选中与不选中是不同结果的
        //ourModel.Draw(cubeShader);
        for (_modelsIter = _models.begin(); _modelsIter != _models.end(); _modelsIter++)
        {
            if (_modelsIter->first == modelSelected)
            {
                glStencilFunc(GL_ALWAYS, 1, 0xFF);
                model = glm::translate(trans, _modelsIter->second.first);
                model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));
                modelShader.useShader();
                modelShader.setMat4("model", model);
                _modelsIter->second.second.Draw(modelShader);
                glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
                glStencilMask(0x00);
                float scale = 1.02;
                model = glm::translate(model, glm::vec3(0.0f, 7.5f, 0.0f));
                model = glm::scale(model, scale * glm::vec3(1, 1, 1));
                model = glm::translate(model, glm::vec3(0.0f, -7.5f, 0.0f));
                stencilShader.useShader();
                stencilShader.setMat4("model", model);
                _modelsIter->second.second.Draw(stencilShader);
                glStencilMask(0xFF);
            }
            else {
                glStencilFunc(GL_ALWAYS, 1, 0xFF);
                model = glm::translate(trans, _modelsIter->second.first);
                model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));
                modelShader.useShader();
                modelShader.setMat4("model", model);
                _modelsIter->second.second.Draw(modelShader);
            }
        }
  • 整体,注意也要添加上清除模板的缓存
  • 注意打开和关闭木板的位置(选中之前打开用完就关闭)
int main() {

	//初始化
	GLFWwindow* window = init(); //创建一个窗口指针,因为里边是一个空指针所有init函数必须改变类型

	//着色    
    Shader modelShader("cube.vert", "cube.frag");
    Shader stencilShader("cube.vert", "stencil.frag");

	//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);   //防止窗口对鼠标进行拦截
  
    glfwSetScrollCallback(window, scroll_callback);
    glEnable(GL_DEPTH_TEST);    //打开深度缓存测试
    glEnable(GL_STENCIL_TEST);  //打开模板测试
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);  //使用执行函数:如果测试不通过就保留,深度测试不通过也保留,都通过就replace

    //使用model类生成model对象
    Model ourModel("D:/openGLResource/bin/nanosuit/nanosuit.obj");

    //下面是两种插入方式,第二种更为简单
    _models.insert(pair<string, pair<glm::vec3, Model>>("Zhang3", pair<glm::vec3, Model>(cubePositions[0], ourModel)));
    _models["Li4"] = pair<glm::vec3, Model>(cubePositions[2], ourModel);


	while (!glfwWindowShouldClose(window)) {    //当需要退出时候退出

		//因为每一个循环的进入时间不一样,确保推进的距离一样,要用到时间差
		currentFrame = glfwGetTime();
		deltaTime = currentFrame - lastFrame;
		lastFrame = currentFrame;

		processInput(window); //每个周期都调用键位函数

		//动态变化摄像机位置
		float radius = 10.0f;   //半径
		float camX = sin(glfwGetTime()) * radius;
		float camZ = cos(glfwGetTime()) * radius;

		//设置颜色值和透明度,需要链接opengl32库才行
		glClearColor(0.2f, 0.3f, 0.3f, 0.1f);   //背景
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);   //清理颜色或者深度缓存以及模板缓存

		//绘制立方体
        glm::mat4 trans = glm::mat4(1.0f);
		model = glm::mat4(1.0f);    //只变换位置用来区分不同的立方体
		view = camera.GetViewMatrix();  //这里每一次都进行了调用
        projection = glm::mat4(1.0f);
		projection = glm::perspective(glm::radians(camera.fov), 800.0f / 600.0f, near,far);  //透视投影:FOV,屏幕长宽比,近,远。
        modelShader.useShader();
		//传值给传送多个矩阵让其发生位置变化
        modelShader.setMat4("projection", projection);
        modelShader.setMat4("view", view);
        modelShader.setVec4("lightPos", cubePositions[1].r, cubePositions[1].g, cubePositions[1].b, 1);
        modelShader.setVec3("viewPos", camera.Position.r, camera.Position.g, camera.Position.b);
        modelShader.setVec3("front", camera.Front.r, camera.Front.g, camera.Front.b);
        modelShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);
        stencilShader.useShader();
        stencilShader.setMat4("projection", projection);
        stencilShader.setMat4("view", view);
        //ourModel.Draw(cubeShader);
        for (_modelsIter = _models.begin(); _modelsIter != _models.end(); _modelsIter++)
        {
            if (_modelsIter->first == modelSelected)//看是否选中
            {

                glStencilFunc(GL_ALWAYS, 1, 0xFF);//如果模型是选中状态的就都写成1(都可以通过)
                model = glm::translate(trans, _modelsIter->second.first);
                model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));
                modelShader.useShader();
                modelShader.setMat4("model", model);
                _modelsIter->second.second.Draw(modelShader);
                
                glStencilFunc(GL_NOTEQUAL, 1, 0xFF);   //使用之前先关闭否则就原来的也给渲染了,如果=1就抛弃你的点
                glStencilMask(0x00);    //任何图形通过都会变成0,关闭
                float scale = 1.02; //比例放大,并且渲染褚放大后的结果
                //先往下移动再旋转再向上上移动
                model = glm::translate(model, glm::vec3(0.0f, 7.5f, 0.0f));
                model = glm::scale(model, scale * glm::vec3(1, 1, 1));
                model = glm::translate(model, glm::vec3(0.0f, -7.5f, 0.0f));
                stencilShader.useShader();
                stencilShader.setMat4("model", model);
                _modelsIter->second.second.Draw(stencilShader);
                glStencilMask(0xFF);//恢复原状
            }
            else {

                glStencilFunc(GL_ALWAYS, 1, 0xFF);
                model = glm::translate(trans, _modelsIter->second.first);
                model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));
                modelShader.useShader();
                modelShader.setMat4("model", model);
                _modelsIter->second.second.Draw(modelShader);
            }
        }	
		glfwPollEvents();   //立即处理已经到位的事件,如果没有这个就会一直渲染而不触发事件       
        glfwSwapBuffers(window);
        modelPicking();
    }
	//退出
	glfwTerminate();
	return 0;
}

结果

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值