2014-07-16 22 views
6

OpenGL ve GLSL'ye yeni geliyorum ve http://open.gl/ aracılığıyla öğreniyorum.Hepsinin yerine bir köşe noktasının rengini nasıl değiştirebilirim?

Bir üçgen çizip kullanan tüm köşelerden rengini değiştirmek başardınız:

glUniform3f(uniColor, red, 0.0, 0.0) 

"kırmızı" değeri sürekli değişen durumlarda, ancak bu tüm tepe arasındaki renk değeri günceller Üçgenin içinde, sadece bir veya iki köşeyi değiştirmek istiyorum. kod üzerinde Looking

Ben (kod neredeyse tamamen http://open.gl/content/code/c2_triangle_uniform.txt dayanmaktadır) yerine hepsini bir tepe ancak bu kodu

odaklanmak için herhangi bir mantık uygulayabilir nerede görmüyorum: http://open.gl/content/code/c2_color_triangle.txt, her vertex kendi rengini alır, ancak kodlanmış gibi görünüyor, program ilerledikçe renkleri dinamik olarak değiştiremiyorum. Ben

uniColor = glGetUniformLocation(shader.handle, "triangleColor") 

tahmin ediyorum

bana değiştirebileceğiniz bir değişkenin yerini verir ve bu değişken tüm köşelerden rengini güncellemek için kullanılır ve bu belki de yapmanız gereken 3 oluşturmaktır değişkenler, her köşe için bir tane ve sonra bunlara erişir, ancak bunu nasıl yaparım?

GLSL'ye bakarsam, "uniform vec3 triangleColor;" bu daha sonra

void main() 
{ 
    outColor = vec4(triangleColor, 1.0); 
} 

kullanılır ama 3 tür triangleColor değişkenler oluşturmak bile nasıl söylerdim void main() Ne değişkeni aldığı köşe ayırt etmek?

kodu:

import pyglet 
from pyglet.gl import * 
from shader import Shader 
from ctypes import pointer, sizeof 
import math 
import time 


window = pyglet.window.Window(800, 600, "OpenGL") 
window.set_location(100, 100) 


# Vertex Input 
## Vertex Array Objects 
vao = GLuint() 
glGenVertexArrays(1, pointer(vao)) 
glBindVertexArray(vao) 

## Vertex Buffer Object 
vbo = GLuint() 
glGenBuffers(1, pointer(vbo)) # Generate 1 buffer 

vertices = [0.0, 0.5, 
      0.5, -0.5, 
      -0.5, -0.5] 
## Convert the verteces array to a GLfloat array, usable by glBufferData 
vertices_gl = (GLfloat * len(vertices))(*vertices) 

## Upload data to GPU 
glBindBuffer(GL_ARRAY_BUFFER, vbo) 
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_gl), vertices_gl, GL_STATIC_DRAW) 


# Shaders (Vertex and Fragment shaders) 
vertex = """ 
#version 150 

in vec2 position; 

void main() 
{ 
    gl_Position = vec4(position, 0.0, 1.0); 
} 
""" 
fragment = """ 
#version 150 

uniform vec3 triangleColor; 

out vec4 outColor; 

void main() 
{ 
    outColor = vec4(triangleColor, 1.0); 
} 
""" 
## Compiling shaders and combining them into a program 
shader = Shader(vertex, fragment) 
shader.bind() #glUseProgram 


# Making the link between vertex data and attributes 
## shader.handle holds the value of glCreateProgram() 
posAttrib = glGetAttribLocation(shader.handle, "position") 
glEnableVertexAttribArray(posAttrib) 
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0) 

uniColor = glGetUniformLocation(shader.handle, "triangleColor") 

# Set clear color 
glClearColor(0.0, 0.0, 0.0, 1.0) 


@window.event 
def on_draw(): 
    # Set the color of the triangle 
    red = (math.sin(time.clock() * 4.0) + 1.0)/2.0 
    glUniform3f(uniColor, red, 0.0, 0.0) 

    # Clear the screen to black 
    glClear(GL_COLOR_BUFFER_BIT) 

    # Draw a triangle from the 3 vertices 
    glDrawArrays(GL_TRIANGLES, 0, 3) 

@window.event 
def on_key_press(symbol, modifiers): 
    pass 

@window.event 
def on_key_release(symbol, modifiers): 
    pass 

def update(dt): 
    pass 
pyglet.clock.schedule(update) 


pyglet.app.run() 
+0

renkleri içeren ikinci bir arabellek yapın, bu sizin konumlarınızla aynı olmalıdır, ancak köşe gölgelendiricisinde kullanmak yerine, bunları parça gölgelendiricisinde kullanabilirsiniz. –

cevap

5

her köşe için bir üniforma ayarlama gerçekten ölçeklenebilir değildir. Değerleri saklamak için başka bir Vertex Buffer Object yaratmak daha iyi bir yol olacaktır. Bu, pozisyonlar için oluşturduğunuza benzer şekilde yapılabilir, ancak bunun dışında 3 GLfloat bulunacaktır. Verileri değiştikçe yeniden tamponlayabilirsiniz.

Benim piton çöp, yani ben bir sözdizimi rehber olarak seninkini kullandım ama çizgisinde bir şey olmalıdır: yeniden tamponlu edilebilir

## Vertex Buffer Object 
vbocolors = GLuint() 
glGenBuffers(1, pointer(vbocolors)) 

colors = [1.0, 0.0, 0.0, # red vertex 
      0.0, 1.0, 0.0, # green vertex 
      0.0, 0.0, 1.0] # blue vertex 

## Convert the verteces array to a GLfloat array, usable by glBufferData 
colors_gl = (GLfloat * len(colors))(*colors) 

## Upload data to GPU 
glBindBuffer(GL_ARRAY_BUFFER, vbocolors) 
glBufferData(GL_ARRAY_BUFFER, sizeof(colors_gl), colors_gl, GL_STATIC_DRAW) 

Sonra yeni renkler:

## Upload new data to GPU 
glBindBuffer(GL_ARRAY_BUFFER, vbocolors) 
glBufferData(GL_ARRAY_BUFFER, sizeof(new_colors_gl), new_colors_gl, GL_STATIC_DRAW) 

Ayar köşe özellik işaretçileri: En gölgelendiricideki Sonra

colorAttrib = glGetAttribLocation(shader.handle, "color") 
glEnableVertexAttribArray(colorAttrib) 
glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0) 

, bu köşe rengini geçmek istiyorum Köşe gölgelendiriciden parça gölgelendiriciye kadar olan değer, rasterleştirme işlemi sırasında değerine uygun olarak enterpolasyon yapar.

# Shaders (Vertex and Fragment shaders) 
vertex = """ 
#version 150 

in vec2 position; 
in vec3 color; 
out vec3 interpColor; 

void main() 
{ 
    gl_Position = vec4(position, 0.0, 1.0); 
    interpColor= color; 
} 
""" 
fragment = """ 
#version 150 

in vec3 interpColor; 
out vec4 outColor; 

void main() 
{ 
    outColor = vec4(interpColor, 1.0); 
} 
""" 
+2

Bunu yapmak için kullanılan deyimsel yöntem, tüm köşe özelliklerini yerleştirmektir. sık sık bir taramalı formatta ortak bir VBO, yani [(x, y, z, r, g, b,…),…] ' – datenwolf

+0

Katılıyorum, ama yeni başlayanlar için iki ayrı VBO önermek daha kolay oldu diye düşünüyorum Geçiş yapmaktan ve işaretçi ofsetlerini kullanmaktan ve özellik işaretçileri için nasıl adım attığınızdan emin olun. – kbirk

+0

Bu durumda, glBufferData() 'içinde' GL_DYNAMIC_DRAW' belirtmek daha iyi olurdu ve sonra renk değerini güncelleştirmek için 'glBufferSubData()' kullanın. –

1

@ Pondwater'ın yanıtında önerilen yaklaşım tamamen geçerli ve makul. Alternatifler her zaman değerli olduğundan, biraz farklı bir yaklaşım.

Buradaki fikir, iki farklı renkte iki üniformanın olması. Hangi verteksin iki renkten hangisini kullandığını belirlemek için, ek bir verttex özniteliği eklersiniz.Bu ek öznitelik, 0.0 değerinin ilk rengi kullanmak istediğiniz ve ikinci rengi kullanmak istediğiniz 1.0 olduğu anlamına gelen tek bir kayan noktadır.

Üçgen örneğiniz için, 1. ve 3. köşe mavi ve 2. köşe kırmızıyı renklendirmek istediğinizi varsayalım. Böyle köşe verileri uzatın:

vertices = [0.0, 0.5, 0.0, 
      0.5, -0.5, 1.0, 
      -0.5, -0.5, 0.0] 

O zaman position için kullanılan aynı desen aşağıdaki (aşağıdaki kodda colorWeight adında) bir ikinci köşe niteliği kurdu. Bu yeni öznitelik için ikinci bir glEnableVertexAttribArray(), glVertexAttribPointer() vb. senin vertex shader olarak

, yeni colorWeight öznitelik eklemek ve parça gölgelendirici onu geçmesine:

in vec2 position; 
in float colorWeight; 
out float fragColorWeight; 

void main() 
{ 
    gl_Position = vec4(position, 0.0, 1.0); 
    fragColorWeight = colorWeight; 
} 

Sonra parça gölgelendirici, artık iki üniforma renkleri var ve bunları esas mix göreceli renk ağırlığı:

uniform vec3 triangleColor; 
uniform vec3 secondaryColor; 
in float fragColorWeight; 
out vec4 outColor; 

void main() 
{ 
    vec3 mixedColor = mix(triangleColor, secondaryColor, fragColorWeight); 
    outColor = vec4(mixedColor, 1.0); 
} 

Şimdi secondaryColor üniforma değişkenin yerini alabilir ve üçgenin sadece ikinci köşe rengini değiştirmek için bağımsız triangleColor arasında ayarlayın.