我有一個kivy應用程序,我希望在特定RenderContext上繪製的所有東西都具有着色器後處理效果(類似於文檔中kivy示例中的EffectWidget示例中演示的效果)。如何更改kivy RenderContext的片段着色器?
在world
控件的構造函數創建了RenderContext
self.prc = RenderContext()
設置它的投影矩陣(這工作)
self.prc['projection_mat'] = proj_mat
,然後嘗試它的片段着色器設置爲最小副本默認的片段着色器應該使所有東西都變爲不透明(基本上調暗屏幕)的十分之一。
self.prc.shader.fs = """
#ifdef GL_ES
precision highp float;
#endif
/* Outputs from the vertex shader */
varying vec4 frag_color;
varying vec2 tex_coord0;
/* uniform texture samplers */
uniform sampler2D texture0;
void main (void){
gl_FragColor = 0.1*frag_color * texture2D(texture0, tex_coord0);
}
"""
如果此着色器的代碼不正確,程序不運行,抱怨着色器的編譯錯誤,這表示着色器正在編制。但是,我沒有看到着色器的任何影響。一切呈現在prc
上,但在正常的不透明度。我究竟做錯了什麼?謝謝你的時間!
編輯!
我被要求提供一個完整的可運行示例。以下程序繪製兩個矩形。左邊的矩形具有自己的RenderContext,不受灰度後處理影響(它被繪製爲紅色)。右邊的矩形沒有自己的RenderContext,它正確地受到後處理影響,因此是。
下面是代碼:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import *
from kivy.graphics.opengl import *
from kivy.graphics.shader import *
from kivy.core.window import Window
from kivy.graphics.transformation import Matrix
from kivy.logger import Logger
class World(Widget) :
def __init__(self, **kwargs):
Logger.debug('world.init()')
# Parent RenderContext for subsuming all other render contexts
self.prc=RenderContext()
proj_mat = Matrix()
proj_mat.look_at(0.,0.,1., # eye position coords
0.,0.,0., # looking at these coords
0,1.,0) # a vector that points up
if Window.height > Window.width :
self.xRadius = float(Window.width)/Window.height
self.yRadius = 1.0
proj_mat.scale(1.0/self.xRadius,1.0,1.0)
else :
self.xRadius = 1.0
self.yRadius = float(Window.height)/Window.width
proj_mat.scale(1.0,1.0/self.yRadius,1.0)
self.prc['projection_mat'] = proj_mat
## an effect shader used to make objects monochromatic (grayscale)
self.prc.shader.fs = """
#ifdef GL_ES
precision highp float;
#endif
/* Outputs from the vertex shader */
varying vec4 frag_color;
varying vec2 vTexCoords0;
/* uniform texture samplers */
uniform sampler2D texture0;
uniform vec2 resolution;
uniform float time;
void main() {
vec4 rgb = texture2D(texture0, vTexCoords0);
float c = (rgb.x + rgb.y + rgb.z) * 0.3333;
gl_FragColor = vec4(c, c, c, 1.0);
}
"""
if not self.prc.shader.success :
raise Exception('Effect shader compile failed.')
self.canvas = self.prc
## Left Rectangle drawn with its own RenderContext
## this is not affected by the effect shader (if it were, it would be drawn as white)
## but it is affected by the parent's projection matrix
self.spriteRC = RenderContext(use_parent_projection=True)
self.spriteRC.add(Color(1,0,0,1))
self.spriteRC.add(Rectangle(pos=(-0.25,0.0),size=(0.1,0.1)))
## Right Rectangle object drawn directly to the canvas
## this **is** affected by the effect shader
self.canvas.add(Color(1,0,0,1))
self.canvas.add(Rectangle(pos=(0.25,0),size=(0.1,0.1)))
self.canvas.add(self.spriteRC)
super(World, self).__init__(**kwargs)
class GameApp(App):
def build(self):
w = World()
fl = FloatLayout()
fl.add_widget(w)
return fl
if __name__ == '__main__':
GameApp().run()
我認爲我的整個方法可能是錯的,也許我想要的功能更好地由kivy的'fbo'類提供。不確定 - 現在正在調查。 – weemattisnot 2014-12-07 19:44:04
要運行示例代碼,我必須在着色器中用''tex_coord0''替換''vTexCoords0''。我有Kivy 1.9.1運行。 – Rolf 2016-05-23 15:48:21