使用以下代码,我可以在openGL控件中显示图像.呈矩形.现在我要将这个矩形的顶部和底部投影到圆柱形状,这意味着需要在openGL上执行从矩形到圆柱的投影.我怎样才能做到这一点?
Using below code I can display an image in openGL control. Which is in rectangular shape. Now I want to project top and bottom area of this rectangular to a cylindrical shape.I mean need to perform a rectangular to cylidrical projection on openGL. How can I achieve this?
private void CreateShaders() { /***********Vert Shader********************/ vertShader = GL.CreateShader(ShaderType.VertexShader); GL.ShaderSource(vertShader, @"attribute vec3 a_position; varying vec2 vTexCoord; void main() { vTexCoord = (a_position.xy + 1) / 2; gl_Position = vec4(a_position, 1); }"); GL.CompileShader(vertShader); /***********Frag Shader ****************/ fragShader = GL.CreateShader(ShaderType.FragmentShader); GL.ShaderSource(fragShader, @"precision highp float; uniform sampler2D sTexture; varying vec2 vTexCoord; void main () { // vec4 color = texture2D (sTexture, vTexCoord); vec2 x =vTexCoord - vec2(0.5); float r = length(x);//radious float u = r*atan( vTexCoord.x/sqrt(r*r-(vTexCoord.x*vTexCoord.x ))); float v = (r*vTexCoord.y)/sqrt(r*r ); vec4 color = texture2D(sTexture, vec2(u, v)); gl_FragColor = color; }"); GL.CompileShader(fragShader); }希望对着色器代码的vTexCoord进行一些更改即可得到结果.
Hope making some changes on vTexCoord of shader code will do the result.
推荐答案
如果要在2d平面上投影2D纹理,因为它将是3D圆柱体,则必须通过 arcus函数( asin 或 acos )在片段着色器中.
If you want to project a 2D textur on a 2d plane as it would be a 3D cylinder, then you have to transform the texture coordinate by an arcus function (asin or acos) in the fragment shader.
必须使用asin函数将[0,1]范围内的纹理坐标与[-90°,90°]范围内的圆角关联.该角度可以线性映射到[0,1]范围内的新纹理坐标.
The texture coordinate in the range [0, 1] have to be associated to an angle on a circle in the range [-90°, 90°] by the asin function. This angle can be linear mapped to the new texture coordinate in the range [0, 1].
该函数的输入是一个角度,返回值是一个距离:
The input to the function is an angle and the return value is a distance:
float u = asin( vTexCoord.x*2.0-1.0 ) / 3.141593 + 0.5;
顶点着色器:
attribute vec3 a_position; varying vec2 vTexCoord; void main() { vTexCoord = (a_position.xy + 1) / 2; gl_Position = vec4(a_position, 1); }片段着色器:
precision highp float; uniform sampler2D sTexture; varying vec2 vTexCoord; void main() { float u = asin( vTexCoord.x*2.0-1.0 ) / 3.141593 + 0.5; float v = vTexCoord.y; vec4 color = texture2D(sTexture, vec2(u, v)); gl_FragColor = color; }查看原始代码的结果和使用asin映射的代码之间的区别:
See the difference between the result of the original code and the code which uses the asin mapping:
在2D平面的投影中,圆柱的顶部和底部为椭圆,可以表示为:
In the projection to a 2D plane, the top and bottom of the cylinder is an ellipse, which can be expressed by:
float b = 0.3; float y = b * sqrt(1.0 - x*x)
必须在顶部和底部挤压纹理的投影以形成椭圆形:
The projection of the texture has to be squeezed at the top and the bottom to form an elliptical shape:
float v_scale = (1.0 + b) / (1.0 + y); float v = (pos.y * v_scale) * 0.5 + 0.5;
必须使用 discard 丢弃被裁剪的区域片段着色器中的a>关键字:
The area which is clipped has to be discarded by using the discard keyword in the fragment shader:
if ( v < 0.0 || v > 1.0 ) discard;查看没有椭圆形失真的结果和使用椭圆形失真的代码之间的区别:
See the difference between the result without the elliptical distortion and the code which uses the elliptical distortion:
结合了asin纹理坐标映射和椭圆形失真的片段着色器:
The fragment shader which combines the asin texture coordinate mapping and the elliptical distortion:
片段着色器:
precision highp float; uniform sampler2D sTexture; varying vec2 vTexCoord; void main() { vec2 pos = vTexCoord.xy * 2.0 - 1.0; float b = 0.3; float v_scale = (1.0 + b) / (1.0 + b * sqrt(1.0 - pos.x*pos.x)); float u = asin( pos.x ) / 3.1415 + 0.5; float v = (pos.y * v_scale) * 0.5 + 0.5; if ( v < 0.0 || v > 1.0 ) discard; vec3 texColor = texture2D( u_texture, vec2(u, v) ).rgb; gl_FragColor = vec4( texColor.rgb, 1.0 ); }组合结果:
更多推荐
如何投影openGL控件的顶部和底部区域
发布评论