首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenGL ES 2.0/3.0中的折射大像素纹理

OpenGL ES 2.0/3.0中的折射大像素纹理
EN

Stack Overflow用户
提问于 2020-05-08 11:50:19
回答 1查看 444关注 0票数 1

尝试在OpenGL ES 2.0/3.0中实现折射。使用下列着色器:

顶点着色器:

代码语言:javascript
复制
#version 300 es
precision lowp float; 
uniform mat4 u_mvMatrix;

in vec4 a_position;  
in vec3 a_normal;
...
out mediump vec2 v_refractCoord;

const mediump float eta = 0.95;

void main() {
    vec4 eyePositionModel = u_mvMatrix * a_position;

    // eye direction in model space
    mediump vec3 eyeDirectModel = normalize(a_position.xyz - eyePositionModel.xyz);

    // calculate refraction direction in model space
    mediump vec3 refractDirect = refract(eyeDirectModel, a_normal, eta);

    // project refraction
    refractDirect = (u_mvpMatrix * vec4(refractDirect, 0.0)).xyw;

    // map refraction direction to 2d coordinates
    v_refractCoord = 0.5 * (refractDirect.xy / refractDirect.z) + 0.5;
    ...
}

碎片着色器:

代码语言:javascript
复制
...
in mediump vec2 v_refractCoord;
uniform samplerCube s_texture; // skybox

void main() {
    outColor = texture(s_texture, vec3(v_refractCoord, 1.0));
}

加载纹理的方法:

代码语言:javascript
复制
@JvmStatic
fun createTextureCubemap(context: Context, rowID: Int) {
    val input = context.resources.openRawResource(rowID)
    val bitmap = BitmapFactory.decodeStream(input)

    val textureId = IntArray(1)
    glGenTextures(1, textureId, 0)
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureId[0])

    GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, bitmap, 0)
    GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, bitmap, 0)
    GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, bitmap, 0)
    GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, bitmap, 0)
    GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, bitmap, 0)
    GLUtils.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, bitmap, 0)

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    return textureId[0]
}

但是纹理是用以下大像素获得的:

这是什么原因?也许这对低聚模型来说是正常的?看起来纹理太近了。

注意:多边形越少,质量就越低。

谢谢您的评论/回答!

来自goodfon.ru的图像

解决方案:对@Rabbid76 76的建议,我改变了正常的数据。结果是,在Blender中,您需要将对象的阴影设置为光滑(无平面)--这将增加导出为*.obj:Why OBJ export writes face normals instead of vertex normals格式时的法线数。

此外,在@Rabbid76 76的建议中,我更改了行文:

代码语言:javascript
复制
vec3 eyeDirectModel = normalize(- eyePositionModel.xyz);

因此,像素化已经消失:

此外,在计算顶点着色器中的折射时,像素伪影也可能出现,因此我将计算结果转移到片段着色器。以下是修改后的着色器代码:

顶点着色器:

代码语言:javascript
复制
#version 300 es
precision lowp float;
uniform mat4 u_mvpMatrix;
uniform mat4 u_mvMatrix;

in vec4 a_position; 
in vec3 a_normal;

out vec3 v_normal;
out lowp float SpecularIntensity;

out vec3 v_eyeDirectModel;

float getSpecularIntensity(vec4 position, vec3 a_normal, vec3 eyeDirectModel) {
    float shininess = 30.0;
    vec3 lightPosition = vec3(-20.0, 0.0, 0.0);
    mediump vec3 LightDirModel = normalize(lightPosition - position.xyz);
    mediump vec3 halfVector = normalize(LightDirModel + eyeDirectModel);
    lowp float NdotH = max(dot(a_normal, halfVector), 0.0);
    return pow(NdotH, shininess);
}

void main() {
    v_normal = a_normal;
    vec4 eyePositionModel = u_mvMatrix * a_position;
    // Eye direction in model space
    vec3 eyeDirectModel = normalize(- eyePositionModel.xyz);
    // specular lighting
    SpecularIntensity = getSpecularIntensity(a_position, a_normal, eyeDirectModel);
    v_eyeDirectModel = eyeDirectModel;
    gl_Position = u_mvpMatrix * a_position;
}

碎片着色器:

代码语言:javascript
复制
#version 300 es
precision lowp float;
uniform mat4 u_mvpMatrix;

in vec3 v_normal;
in lowp float SpecularIntensity;
in vec3 v_eyeDirectModel;

out vec4 outColor; 
uniform samplerCube s_texture; // skybox

const float eta = 0.65;
void main() {
    // Calculate refraction direction in model space
    vec3 refractDirect = refract(v_eyeDirectModel, normalize(v_normal), eta);
    // Project refraction
    refractDirect = (u_mvpMatrix * vec4(refractDirect, 0.0)).xyw;
    // Map refraction direction to 2d coordinates
    vec2 refractCoord = 0.5 * (refractDirect.xy / refractDirect.z) + 0.5;

    vec4 glassColor = texture(s_texture, vec3(refractCoord, 1.0));
    outColor = glassColor + SpecularIntensity;
    outColor.a = 0.8; // transparent
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-16 11:49:44

首先,在着色器代码中有一个错误。a_position.xyz - eyePositionModel.xyz没有任何意义,因为a_position是模型空间中的顶点坐标,eyePositionModel是视图空间中的顶点坐标。

您必须在视图sapce中计算refract的事件向量。这是从眼睛位置到顶点的向量。由于眼睛在视图空间中的位置是(0,0,0),它是:

代码语言:javascript
复制
vec4 eyePositionView = u_mvMatrix * a_position;

// eye direction in model space
mediump vec3 eyeDirectView = normalize(- eyePositionView.xyz);

此外,这是一个关于法向量属性的问题。这个问题是由这样一个事实引起的:法线向量是每面计算的,而不是每个顶点单独计算的。

注意,折射方向(refractDirect)取决于顶点坐标(eyeDirectModel)和法向量(a_normal):

代码语言:javascript
复制
mediump vec3 refractDirect = refract(eyeDirectModel, a_normal, eta);

因为法向量在相邻的表面之间是不同的,所以你可以看到网格表面之间明显的边缘。

如果每个顶点计算法向量,则相邻面共享顶点坐标和对应的法向量。这将导致从面对面到面对面的平稳过渡。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61678506

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档