From 4059101aa792ff59ff722d91b5b7ab336e0228d2 Mon Sep 17 00:00:00 2001 From: wuyize Date: Fri, 22 Jul 2022 16:36:48 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A5=9E=E8=AF=B4=EF=BC=8C=E8=A6=81=E6=9C=89?= =?UTF-8?q?=E5=85=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ArchitectureColoredPainting/Mesh.cpp | 16 +-- ArchitectureColoredPainting/Model.cpp | 24 ++-- .../RendererWidget.cpp | 50 ++++--- ArchitectureColoredPainting/RendererWidget.h | 3 +- .../Shaders/shader.frag | 133 +++++++++++++++++- .../Shaders/shader.vert | 9 +- README.md | 6 +- 7 files changed, 183 insertions(+), 58 deletions(-) diff --git a/ArchitectureColoredPainting/Mesh.cpp b/ArchitectureColoredPainting/Mesh.cpp index 0a9283c..adb5fdc 100644 --- a/ArchitectureColoredPainting/Mesh.cpp +++ b/ArchitectureColoredPainting/Mesh.cpp @@ -23,19 +23,11 @@ void Mesh::Draw() for (unsigned int i = 0; i < textures.size(); i++) { glFunc->glActiveTexture(GL_TEXTURE0 + i); // 在绑定之前激活相应的纹理单元 - // 获取纹理序号(diffuse_textureN 中的 N) - QString number; - QString name = textures[i]->type; - if (name == "texture_diffuse") - number = QString::number(diffuseNr++); - else if (name == "texture_specular") - number = QString::number(specularNr++); - else if (name == "texture_normal") - number = QString::number(normalNr++); // transfer unsigned int to stream - else if (name == "texture_height") - number = QString::number(heightNr++); // transfer unsigned int to stream + + textures[i]->texture.bind(); - shaderProgram->setUniformValue((name + number).toStdString().c_str(), i); + //qDebug() << name + number; + shaderProgram->setUniformValue(textures[i]->type.toStdString().c_str(), i); } // 绘制网格 diff --git a/ArchitectureColoredPainting/Model.cpp b/ArchitectureColoredPainting/Model.cpp index 7bfad0c..a42945e 100644 --- a/ArchitectureColoredPainting/Model.cpp +++ b/ArchitectureColoredPainting/Model.cpp @@ -17,7 +17,7 @@ Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shader qDebug() << "ERROR::ASSIMP::" << import.GetErrorString() << endl; return; } - qDebug() << directory.absolutePath() << "Load Successfully"; + qDebug() << directory.absolutePath() << "Loaded Successfully"; qDebug() << "NumMeshes: " << scene->mNumMeshes; qDebug() << "NumMaterials: " << scene->mNumMaterials; qDebug() << "NumTextures: " << scene->mNumTextures; @@ -45,8 +45,8 @@ void Model::draw() { void Model::destroy() { + context->doneCurrent(); delete this; - context->doneCurrent(); } Model* Model::createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram) @@ -135,35 +135,29 @@ Mesh* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model) // 处理材质 aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; - // 1. 漫反射贴图 - QVector diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse"); + QVector diffuseMaps = loadMaterialTextures(material, aiTextureType_BASE_COLOR, "texture_basecolor"); for (auto& it : diffuseMaps) m_mesh->textures.push_back(it); - // 2. 镜面贴图 - QVector specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular"); - for (auto& it : specularMaps) + QVector metalnessMaps = loadMaterialTextures(material, aiTextureType_METALNESS, "texture_metallic_roughness"); + for (auto& it : metalnessMaps) m_mesh->textures.push_back(it); - // 3. 法向量图 - QVector normalMaps = loadMaterialTextures(material, aiTextureType_HEIGHT, "texture_normal"); + QVector normalMaps = loadMaterialTextures(material, aiTextureType_NORMALS, "texture_normal"); for (auto& it : normalMaps) m_mesh->textures.push_back(it); - // 4. 高度图 - QVector heightMaps = loadMaterialTextures(material, aiTextureType_AMBIENT, "texture_height"); - for (auto& it : heightMaps) - m_mesh->textures.push_back(it); - m_mesh->setupMesh(); return m_mesh; } QVector Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, QString typeName) { - QVector textures; + QVector textures; + for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) { + //qDebug() << typeName; aiString str; mat->GetTexture(type, i, &str); diff --git a/ArchitectureColoredPainting/RendererWidget.cpp b/ArchitectureColoredPainting/RendererWidget.cpp index 0e4d434..669a5b3 100644 --- a/ArchitectureColoredPainting/RendererWidget.cpp +++ b/ArchitectureColoredPainting/RendererWidget.cpp @@ -5,13 +5,12 @@ #include RendererWidget::RendererWidget(QWidget* parent) - : QOpenGLWidget(parent), camera(QVector3D(0.0f, 0.0f, 3.0f)) + : QOpenGLWidget(parent), camera(QVector3D(0.0f, 100.0f, 0.0f)) { startTimer(1000 / 120); lastFrame = std::clock(); setFocusPolicy(Qt::StrongFocus); - setMouseTracking(true); - setCursor(Qt::BlankCursor); + } RendererWidget::~RendererWidget() @@ -69,7 +68,8 @@ void RendererWidget::initializeGL() reinterpret_cast(3 * sizeof(GLfloat))); m_vbo.release();*/ } - +QVector3D lightPositions[] = { QVector3D(0,0,0), QVector3D(100,100,100) ,QVector3D(-100,100,100) ,QVector3D(100,100,-100) }; +QVector3D lightColors[] = { QVector3D(150000,150000,150000), QVector3D(0,0,0) ,QVector3D(0,0,0) ,QVector3D(0,0,0) }; void RendererWidget::paintGL() { //std::cout << (double)CLOCKS_PER_SEC/(std::clock() -lastFrame) << std::endl; @@ -81,6 +81,10 @@ void RendererWidget::paintGL() // camera/view transformation QMatrix4x4 view = camera.GetViewMatrix(); m_program->setUniformValue(m_program->uniformLocation("view"), view); + m_program->setUniformValue(m_program->uniformLocation("camPos"), camera.Position); + lightPositions[0] = camera.Position; + m_program->setUniformValueArray("lightPositions", lightPositions, 4); + m_program->setUniformValueArray("lightColors", lightColors, 4); //glDrawArrays(GL_TRIANGLES, 0, 3); model->draw(); m_program->release(); @@ -90,7 +94,7 @@ void RendererWidget::resizeGL(int width, int height) { m_program->bind(); QMatrix4x4 projection; - projection.perspective(camera.Zoom, (float)width / (float)height, 0.1f, 10000.0f); + projection.perspective(camera.Zoom, (float)width / (float)height, 10.f, 10000.0f); m_program->setUniformValue(m_program->uniformLocation("projection"), projection); } @@ -100,9 +104,16 @@ void RendererWidget::timerEvent(QTimerEvent* event) clock_t currentFrame = std::clock(); deltaTime = (float)(std::clock() - lastFrame) / CLOCKS_PER_SEC; lastFrame = currentFrame; - if (pressedKeys.contains(Qt::Key_Escape)) { - close(); + + if (hasFocus()) + { + QPoint center = mapToGlobal(geometry().center()); + float xoffset = cursor().pos().x() - center.x(); + float yoffset = center.y() - cursor().pos().y(); + camera.ProcessMouseMovement(xoffset, yoffset); + cursor().setPos(center); } + if (pressedKeys.contains(Qt::Key_W)) { camera.ProcessKeyboard(FORWARD, deltaTime); } @@ -126,7 +137,9 @@ void RendererWidget::timerEvent(QTimerEvent* event) void RendererWidget::keyPressEvent(QKeyEvent* event) { - if (!event->isAutoRepeat()) + if (event->key() == Qt::Key_Escape) + clearFocus(); + else if (!event->isAutoRepeat()) pressedKeys.insert(event->key()); QOpenGLWidget::keyPressEvent(event); } @@ -138,20 +151,15 @@ void RendererWidget::keyReleaseEvent(QKeyEvent* event) QOpenGLWidget::keyReleaseEvent(event); } -void RendererWidget::mouseMoveEvent(QMouseEvent* event) + +void RendererWidget::focusInEvent(QFocusEvent* event) { - static bool firstMouse = true; - if (firstMouse) - { - firstMouse = false; - } - else - { - float xoffset = event->pos().x() - geometry().center().x(); - float yoffset = geometry().center().y() - event->pos().y(); - camera.ProcessMouseMovement(xoffset, yoffset); - } + setCursor(Qt::BlankCursor); cursor().setPos(mapToGlobal(geometry().center())); - QOpenGLWidget::mouseMoveEvent(event); +} + +void RendererWidget::focusOutEvent(QFocusEvent* event) +{ + setCursor(Qt::ArrowCursor); } diff --git a/ArchitectureColoredPainting/RendererWidget.h b/ArchitectureColoredPainting/RendererWidget.h index 9e98af7..3b25b67 100644 --- a/ArchitectureColoredPainting/RendererWidget.h +++ b/ArchitectureColoredPainting/RendererWidget.h @@ -23,7 +23,8 @@ protected: void timerEvent(QTimerEvent* event) override; void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; - void mouseMoveEvent(QMouseEvent* event) override; + void focusInEvent(QFocusEvent* event) override; + void focusOutEvent(QFocusEvent* event) override; private: QSet pressedKeys; Camera camera; diff --git a/ArchitectureColoredPainting/Shaders/shader.frag b/ArchitectureColoredPainting/Shaders/shader.frag index 6efa237..31971f1 100644 --- a/ArchitectureColoredPainting/Shaders/shader.frag +++ b/ArchitectureColoredPainting/Shaders/shader.frag @@ -1,12 +1,133 @@ #version 330 core + +uniform sampler2D texture_basecolor; +uniform sampler2D texture_metallic_roughness; +uniform sampler2D texture_normal; + +out vec4 FragColor; in vec2 TexCoords; - -uniform sampler2D texture_diffuse1; - -void main() +in vec3 WorldPos; +in vec3 Normal; + +// lights +uniform vec3 lightPositions[4]; +uniform vec3 lightColors[4]; + +uniform vec3 camPos; + +const float PI = 3.14159265359; + +vec3 getNormalFromMap() { - gl_FragColor = texture2D(texture_diffuse1,TexCoords); - if(gl_FragColor.a==0) + vec3 tangentNormal = texture(texture_normal, TexCoords).xyz * 2.0 - 1.0; + + vec3 Q1 = dFdx(WorldPos); + vec3 Q2 = dFdy(WorldPos); + vec2 st1 = dFdx(TexCoords); + vec2 st2 = dFdy(TexCoords); + + vec3 N = normalize(Normal); + vec3 T = normalize(Q1*st2.t - Q2*st1.t); + vec3 B = -normalize(cross(N, T)); + mat3 TBN = mat3(T, B, N); + + return normalize(TBN * tangentNormal); +} +// ---------------------------------------------------------------------------- +float DistributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySchlickGGX(float NdotV, float roughness) +{ + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} +// ---------------------------------------------------------------------------- +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} +// ---------------------------------------------------------------------------- +vec3 fresnelSchlick(float cosTheta, vec3 F0) +{ + return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); +} +void main() +{ + vec4 baseColor = texture(texture_basecolor, TexCoords); + if(baseColor.a==0) discard; + + vec3 albedo = pow(baseColor.rgb, vec3(2.2)); + float metallic = texture(texture_metallic_roughness, TexCoords).b; + float roughness = texture(texture_metallic_roughness, TexCoords).g; + + + vec3 N = getNormalFromMap(); + vec3 V = normalize(camPos - WorldPos); + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + // reflectance equation + vec3 Lo = vec3(0.0); + for(int i = 0; i < 1; ++i) + { + // calculate per-light radiance + vec3 L = normalize(lightPositions[i] - WorldPos); + vec3 H = normalize(V + L); + float distance = length(lightPositions[i] - WorldPos); + float attenuation = 1.0 / (distance * distance); + vec3 radiance = lightColors[i] * attenuation; + + // cook-torrance brdf + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + F = clamp(F,vec3(0),vec3(1)); + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + vec3 nominator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001; + vec3 specular = nominator / denominator; + + // add to outgoing radiance Lo + float NdotL = max(dot(N, L), 0.0); + Lo += (kD * albedo / PI + specular) * radiance * NdotL; + + } + + vec3 ambient = vec3(0.03) * albedo; + vec3 color = ambient + Lo; + + color = color / (color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); + + FragColor = vec4(color, 1.0); + } \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/shader.vert b/ArchitectureColoredPainting/Shaders/shader.vert index 91e43a2..8e2587b 100644 --- a/ArchitectureColoredPainting/Shaders/shader.vert +++ b/ArchitectureColoredPainting/Shaders/shader.vert @@ -4,6 +4,8 @@ layout (location = 1) in vec3 aNormal; layout (location = 2) in vec2 aTexCoords; out vec2 TexCoords; +out vec3 WorldPos; +out vec3 Normal; uniform mat4 model; uniform mat4 view; @@ -12,6 +14,9 @@ uniform mat4 projection; void main() { TexCoords = aTexCoords; - gl_Position = projection * view * model * vec4(aPos, 1.0); + WorldPos = vec3(model * vec4(aPos, 1.0)); + Normal = mat3(model) * aNormal; + + gl_Position = projection * view * vec4(WorldPos, 1.0); -} +} \ No newline at end of file diff --git a/README.md b/README.md index f3f8f22..c28cd9c 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ -# ArchitectureColoredPainting \ No newline at end of file +# ArchitectureColoredPainting + +閲囩敤pbr鏉愯川锛岀幇鍦ㄦ湁涓涓厜婧愬拰鎽勫儚鏈虹粦瀹氾紝瓒充互鍒嗚鲸鍑轰笉鍚屾潗璐ㄧ殑鏁堟灉 + +TODO锛氭敼鐢ㄥ欢杩熸覆鏌擄紝骞舵寚瀹氫竴鍧楁潗璐ㄤ娇鐢ㄧ嫭绔嬬绾胯繘琛岀汗鐞嗛噰鏍 \ No newline at end of file