2

我正在为 iOS 创建一个 ios 绘画应用程序,并且最难在特定点旋转绘画纹理以使其面向笔画方向。

我在用户的每次触摸之间绘制了几个像素的纹理。顶点被表示为具有 x 和 y 坐标的 2d 点到顶点缓冲区中,然后将其渲染到屏幕上。这是我用来绘制的代码:

 count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y)) / kBrushPixelStep), 1);
 GLfloat *vBuffer = malloc(2 * sizeof(GLfloat));
 for(i = 0; i < count; i++) {

    vBuffer[0] = start.x + (end.x - start.x) * ((GLfloat)i / (GLfloat)count);
    vBuffer[1] = start.y + (end.y - start.y) * ((GLfloat)i / (GLfloat)count);
    CGFloat degrees = atan2(end.y - start.y, end.x - start.x) * 180 / M_PI;

    glMatrixMode(GL_TEXTURE);
    glPushMatrix();
    glVertexPointer(2, GL_FLOAT, 0, vBuffer);
    glDrawArrays(GL_POINTS, 0, count);
    glRotatef(degrees, 0, 0, 1);
    glPopMatrix();
 }

 // render to screen
 glBindRenderbufferOES(GL_RENDERBUFFER_OES, renderbuffer);
 [context presentRenderbuffer:GL_RENDERBUFFER_OES];

这并没有给我想要的效果,即纹理在每个顶点处的旋转角度表示两点之间的偏差。

我的问题是:

  • 如何在每个点仅旋转纹理?
  • 仅用 x,y 坐标表示每个顶点是否足够,还是必须为 3 个点或更多?
  • 我需要启用纹理映射吗?那是什么阻止我在每个顶点独立旋转纹理?如果是这样,我如何表示上面表示的顶点数组的纹理坐标数组?我一直无法弄清楚那部分。

非常感谢您提前提供的帮助!

更新:

我能够弄清楚这一点并在此处发布我的答案:https ://stackoverflow.com/a/11298219/111856

4

3 回答 3

5

如果您是通过 google 搜索到达此页面(几乎每个人都会这样做),您可能想知道如何旋转使用 gl_PointCoord 渲染的精灵。SteveL 接受的答案错误地表示这是不可能的,但 Joel Murphy 指出了如何做到这一点。

如果您使用 Joel 的建议,以下是一些可能与您相关的附加信息。(在我的书中,贡献信息与实际答案一样接近,没有区别!)

  1. 图像需要是原始大小的 2 倍,即 1.414 x,而不是 15%
  2. 在顶点着色器中进行三角函数工作的效率要高得多。所以我有:

    precision mediump float;
    
    attribute vec3 vertex;
    attribute vec3 normal;
    
    uniform mat4 modelviewmatrix[2];
    uniform vec3 unib[4];
    
    varying float dist;
    varying mat2 rotn;
    
    void main(void) {
      gl_Position = modelviewmatrix[1] * vec4(vertex,1.0);
      dist = vertex[2];
      rotn = mat2(cos(normal[0]), sin(normal[0]),
                 -sin(normal[0]), cos(normal[0])); 
      gl_PointSize = unib[2][2] / dist;
    }
    

    片段着色器:

    precision mediump float;
    
    uniform sampler2D tex0;
    uniform vec3 unib[4];
    
    varying float dist;
    varying mat2 rotn;
    
    void main(void) {
      vec2 centre = vec2(0.5, 0.5);
      vec2 rot_coord = rotn * (gl_PointCoord - centre) + centre;
      vec4 texc = texture2D(tex0, rot_coord);
      if (dist < 1.0 || texc.a < unib[0][2]) discard;
      gl_FragColor = texc;
    }
    

PS 我不再使用 highp 变量,因为 beaglebone 和 cubitruck 等 soc 板上使用的一些电话 gpus 不支持它。

PPS 作为对这种方法的扩展,我在 pi3d 中添加了这个着色器的一个版本,它也使用偏移量来使用 texture2D() 作为精灵图集。顶点 片段

于 2015-03-25T07:43:47.070 回答
3

通过从顶点着色器传递旋转值,我已经能够在片段着色器中旋转纹理。给定具有以下内容的顶点着色器:

attribute float aRotation;
varying float vRotation;

属性从您的应用程序传递,而变化将信息传递给片段着色器。不需要计算任何内容,因此您可以通过将其放在顶点着色器的 main() 函数中直接复制该值:

vRotation = aRotation;

在片段着色器中,您需要有另一个不同的语句:

varying highp float vRotation;

值 gl_PointCoord 是一个 vec2,其值介于 0.0 和 1.0 之间,(0.0, 0.0) 是左下角,(1.0, 1.0) 是右上角,因此只需进行很少的转换即可完成这项工作。在片段着色器的主目录中,添加:

// Set a center position.
highp vec2 center = vec2(0.5, 0.5);

// Translate the center of the point the origin.
highp vec2 centeredPoint = gl_PointCoord - center;

// Create a rotation matrix using the provided angle
highp mat2 rotation = mat2(cos(vRotation), sin(vRotation),
                          -sin(vRotation), cos(vRotation)); 

// Perform the rotation.
centeredPoint = rotation * centeredPoint;

// Translate the point back to its original position and use that point 
// to get your texture color.
gl_FragColor = texture2D(uTexture, centeredPoint + center);

注意:实际的点精灵仍然是引擎绘制的同一个正方形。如果使用这种方法,你需要确保你的纹理每边有大约 15% 的填充(例如,如果你的图像是 128x128,你需要用 56 像素的边距填充图像)。

于 2014-01-14T20:03:38.990 回答
0

绘制为 GL_POINTS 时无法旋转点,您需要使用其他方式,例如将纹理绘制为 GL_TRIANGLES

于 2012-06-30T19:47:49.213 回答