2013-03-06 9 views
25

Tôi đã vẽ hình thang kết cấu, tuy nhiên kết quả không xuất hiện như tôi đã dự định.Phối cảnh kết cấu chính xác của hình thang trong OpenGL ES 2.0

Thay vì xuất hiện dưới dạng tứ giác đơn không gián đoạn, sự gián đoạn xảy ra ở đường chéo nơi hai hình tam giác của nó gặp nhau.

minh họa này cho thấy vấn đề này:
Illustration demonstrating the source texture (a checkered pattern), the expected result, and the actual (incorrect) result
(Lưu ý:. Hình ảnh cuối cùng không có ý định trở thành một 100% đại diện trung thành, nhưng nó phải được những điểm trên)

Các hình thang đã được rút ra sử dụng GL_TRIANGLE_STRIP trong OpenGL ES 2.0 (trên iPhone). Nó đang được vẽ hoàn toàn đối diện với màn hình, và không bị nghiêng (tức là đó không phải là một bản phác họa 3D mà bạn đang thấy!)

Tôi đã hiểu rằng tôi cần phải thực hiện "hiệu chỉnh phối cảnh", có lẽ là ở đỉnh của tôi và/hoặc shaders fragment, nhưng tôi không rõ làm thế nào để làm điều này.

Mã của tôi bao gồm một số phép toán ma trận Model/View/Projection đơn giản, nhưng không có phép toán nào trong số đó ảnh hưởng đến giá trị tọa độ kết cấu của tôi. Cập nhật: Câu lệnh trước không chính xác, theo nhận xét của người dùng.

Hơn nữa, tôi đã tìm thấy miếng ngon này trong spec ES 2.0, nhưng không hiểu ý nghĩa của nó:

quan điểm SỬA CHỮA GỢI Ý không được hỗ trợ vì OpenGL ES 2.0 yêu cầu tất cả các thuộc tính được perspectively nội suy.

Làm cách nào để vẽ kết cấu chính xác?


Edit: Added mã bên dưới:

// Vertex shader 
attribute vec4 position; 
attribute vec2 textureCoordinate; 

varying vec2 texCoord; 

uniform mat4 modelViewProjectionMatrix; 

void main() 
{ 
    gl_Position = modelViewProjectionMatrix * position; 
    texCoord = textureCoordinate; 
} 

// Fragment shader 
uniform sampler2D texture; 
varying mediump vec2 texCoord; 

void main() 
{ 
    gl_FragColor = texture2D(texture, texCoord); 
} 

// Update and Drawing code (uses GLKit helpers from iOS) 

- (void)update 
{ 
    float fov = GLKMathDegreesToRadians(65.0f); 
    float aspect = fabsf(self.view.bounds.size.width/self.view.bounds.size.height); 
    projectionMatrix = GLKMatrix4MakePerspective(fov, aspect, 0.1f, 50.0f); 
    viewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); // zoom out 
} 

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect 
{ 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glUseProgram(shaders[SHADER_DEFAULT]); 

    GLKMatrix4 modelMatrix = GLKMatrix4MakeScale(0.795, 0.795, 0.795); // arbitrary scale 

    GLKMatrix4 modelViewMatrix = GLKMatrix4Multiply(viewMatrix, modelMatrix); 

    GLKMatrix4 modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); 
    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, GL_FALSE, modelViewProjectionMatrix.m); 

    glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_WALLS]); 
    glUniform1i(uniforms[UNIFORM_TEXTURE], 0); 

    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, wall.vertexArray); 
    glVertexAttribPointer(ATTRIB_TEXTURE_COORDINATE, 2, GL_FLOAT, GL_FALSE, 0, wall.texCoords); 
    glDrawArrays(GL_TRIANGLE_STRIP, 0, wall.vertexCount); 

} 
+0

Hình dạng có phải là hình tứ giác đã được biến đổi và chiếu, hay đây là hình dạng 2D tùy ý? Giải pháp đơn giản nhất là chỉ cần render một quad nghiêng trong 3D ... – JasonD

+0

Bạn nên kiểm tra UV cho tam giác thứ hai.Looks như thay đổi kết cấu –

+1

Hiển thị mã cho chúng tôi. Có vẻ hơi bị _backshortened _... –

Trả lời

17

(Tôi đang tham gia một chút của một punt đây, vì hình ảnh của bạn không không hiển thị chính xác những gì tôi mong đợi từ việc tạo họa tiết hình thang oid, vì vậy có lẽ một cái gì đó khác đang xảy ra trong trường hợp của bạn - nhưng vấn đề chung là nổi tiếng)

Kết cấu sẽ không (theo mặc định) nội suy chính xác trên hình thang. Khi hình tam giác để vẽ, một trong các đường chéo sẽ được chọn làm cạnh, và trong khi cạnh đó thẳng qua giữa của kết cấu, nó không phải là qua giữa hình thang (hình dạng hình được chia dọc theo đường chéo - hai hình tam giác là rất nhiều không bằng nhau).

Bạn cần cung cấp phối cảnh kết cấu 2D để thực hiện công việc này - bạn cần cung cấp tọa độ kết cấu 3D (hoặc đúng hơn), và thực hiện phối cảnh trong trình đổ bóng phân đoạn, sau nội suy (hoặc sử dụng chức năng tra cứu kết cấu sẽ thực hiện tương tự).

Phần sau đây cho thấy cách cung cấp tọa độ kết cấu cho hình thang sử dụng hàm GL cũ (dễ đọc hơn một chút cho mục đích trình diễn). Các dòng chú thích là các tọa độ kết cấu 2d, mà tôi đã thay thế bằng các tọa độ dự báo để có được nội suy chính xác.

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glOrtho(0,640,0,480,1,1000); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 

const float trap_wide = 600; 
const float trap_narrow = 300; 
const float mid = 320; 

glBegin(GL_TRIANGLE_STRIP); 
glColor3f(1,1,1); 

// glTexCoord4f(0,0,0,1); 
glTexCoord4f(0,0,0,trap_wide); 
glVertex3f(mid - trap_wide/2,10,-10); 

// glTexCoord4f(1,0,0,1); 
glTexCoord4f(trap_narrow,0,0,trap_narrow); 
glVertex3f(mid - trap_narrow/2,470,-10); 

// glTexCoord4f(0,1,0,1); 
glTexCoord4f(0,trap_wide,0,trap_wide); 
glVertex3f(mid + trap_wide/2,10,-10); 

// glTexCoord4f(1,1,0,1); 
glTexCoord4f(trap_narrow,trap_narrow,0,trap_narrow); 
glVertex3f(mid + trap_narrow/2,470,-10); 

glEnd(); 

Tọa độ thứ ba không được sử dụng ở đây vì chúng tôi chỉ sử dụng kết cấu 2D. Tọa độ thứ tư sẽ chia hai số còn lại sau nội suy, cung cấp phép chiếu. Rõ ràng nếu bạn chia nó qua các đỉnh, bạn sẽ thấy bạn có được tọa độ kết cấu ban đầu.

Đây là những gì hai render trông giống như:

enter image description here

Nếu hình thang của bạn thực sự là kết quả của việc chuyển đổi một quad, nó có thể được dễ dàng hơn/tốt hơn để chỉ cần vẽ quad rằng việc sử dụng GL, chứ không phải là chuyển nó trong phần mềm và cho hình dạng 2D để GL ...

+0

Thật không may 'GL_QUAD' không có trong OpenGL ES 2.0. Cách tiếp cận này có thể được điều chỉnh để làm việc với 'GL_TRIANGLE_STRIP' và ES 2.0 không? Cụ thể, tôi chỉ cố gắng thực hiện ở trên và không chắc chắn làm thế nào để sử dụng thêm hai tọa độ kết cấu trong bóng đổ của tôi. – Neema

+0

Quad là một sự không liên quan, nó có thể là hai hình tam giác. Trong hai tọa độ kết cấu bổ sung, một tọa độ không được sử dụng, cái kia nên được sử dụng để phân chia hai cái đầu tiên, giống như với một biến đổi phối cảnh. – JasonD

+1

Tôi đang cố gắng áp dụng ví dụ của bạn ở trên cho mã thử nghiệm của mình.Tại thời điểm này, tôi đã phát hiện ra rằng tôi có thể sử dụng 'texture2DProj()' trong shader fragment của tôi thay vì chia cho texCoord.w. Tôi nghĩ rằng đây là giải pháp, và bây giờ tôi chỉ cần làm cho nó hoạt động. – Neema

0

Những gì bạn đang cố gắng ở đây là kết cấu Skewed. Một shader đoạn mẫu như sau:

precision mediump float; 
varying vec4 vtexCoords; 
uniform sampler2D sampler; 

void main() 
{ 
    gl_FragColor = texture2DProj(sampler,vtexCoords); 
} 

2 điều mà nên nhìn khác nhau là:

1) Chúng tôi đang sử dụng varying vec4 vtexCoords;. Các tọa độ kết cấu là 4 chiều. 2) texture2DProj() được sử dụng thay vì texture2D()

Dựa trên chiều dài cạnh nhỏ và lớn của hình thang, bạn sẽ gán tọa độ kết cấu. Sau URL có thể giúp: http://www.xyzw.us/~cass/qcoord/

0

Câu trả lời được chấp nhận cung cấp cho các giải pháp đúng và giải thích nhưng đối với những người tìm kiếm sự giúp đỡ hơn một chút trên OpenGL (ES) 2.0 đường ống ...

const GLfloat L = 2.0; 
const GLfloat Z = -2.0; 
const GLfloat W0 = 0.01; 
const GLfloat W1 = 0.10; 

/** Trapezoid shape as two triangles. */ 
static const GLKVector3 VERTEX_DATA[] = { 
    {{-W0, 0, Z}}, 
    {{+W0, 0, Z}}, 
    {{-W1, L, Z}}, 

    {{+W0, 0, Z}}, 
    {{+W1, L, Z}}, 
    {{-W1, L, Z}}, 
}; 

/** Add a 3rd coord to your texture data. This is the perspective divisor needed in frag shader */ 
static const GLKVector3 TEXTURE_DATA[] = { 
    {{0, 0, 0}}, 
    {{W0, 0, W0}}, 
    {{0, W1, W1}}, 

    {{W0, 0, W0}}, 
    {{W1, W1, W1}}, 
    {{0, W1, W1}}, 
}; 

//////////////////////////////////////////////////////////////////////////////////// 

// frag.glsl 

varying vec3 v_texPos; 
uniform sampler2D u_texture; 

void main(void) 
{ 
    // Divide the 2D texture coords by the third projection divisor 
    gl_FragColor = texture2D(u_texture, v_texPos.st/v_texPos.p); 
} 

Ngoài ra, trong đổ bóng, như mỗi câu trả lời @ maverick9888 của, Bạn có thể sử dụng texture2Dproj dù cho iOS/OpenGLES2 nó vẫn chỉ hỗ trợ một đầu vào vec3 ...

void main(void) 
{ 
    gl_FragColor = texture2DProj(u_texture, v_texPos); 
} 

tôi đã không thực sự benchmarked nó p roperly nhưng đối với trường hợp rất đơn giản của tôi (một kết cấu 1d thực sự) phiên bản phân chia có vẻ hơi snappier.

+0

Tôi mong đợi phiên bản phân chia sẽ chậm hơn phiên bản 'texture2DProj', vì nó làm cho kết cấu phụ thuộc bị đọc. – Tenfour04

+0

Bạn có ý nghĩa gì bởi "đọc kết cấu phụ thuộc"? –

+1

http://stackoverflow.com/a/27028431/506796 Trên GPU di động, rất nhiều tối ưu hóa bị mất nếu cuộc gọi đọc từ kết cấu sử dụng bất kỳ thứ gì nhưng được truyền trực tiếp trong vectơ (hoặc thành phần pq của vec 4). – Tenfour04