OpenGL超級寶典筆記——累積緩衝區與其餘顏色操做

累積緩衝區

OpenGL除了顏色緩衝區、深度緩衝區、模板緩衝區以外,還有累積緩衝區。累積緩衝區容許你把渲染到顏色緩衝區的值,拷貝到累積緩衝區。在屢次拷貝操做到累積緩衝區時,能夠用不一樣方式的把顏色緩衝區內容和當前累積緩衝區的內容進行重複混合。當在累積緩衝區完成一幅圖像以後,能夠拷回顏色緩衝區,而後經過SwapBuffers顯示到屏幕上。函數

累積緩衝區的操做經過void glAccum(GLenum op, GLfloat value);控制。第一個參數表示對累積緩衝區所進行的操做。第二個參數是浮點數用於指定縮放因子。oop

OpenGL支持的累積緩衝區的操做以下表:性能

操做 描述
GL_ACCUM 把顏色緩衝區的顏色值進行縮放後,累加到累積緩衝區
GL_LOAD 把顏色緩衝區的顏色值進行縮放後,替換掉累積緩衝區的顏色值
GL_RETURN 把累積緩衝區的顏色值縮放後,拷貝回顏色緩衝區
GL_MULT 把累積緩衝區的顏色值縮放後,替換掉原累積緩衝區的顏色值
GL_ADD 把累積緩衝區的顏色值縮放後,累加到累積緩衝區

因爲累積緩衝區會帶來大內存的開銷,因此在實時應用程序中比較少用。但在非實時的應用程序中,能夠產生實時應用程序沒法作到的效果。例如,你能夠屢次渲染場景,並在每次渲染時進行抖動零點幾個像素,這樣就能夠產生整個場景的反走樣的效果,比多重採樣的效果還要好。還能夠模糊前景或背景,而後清晰的渲染一個物體來模擬,照相機景深的效果。測試

image

下面的例子是一個球體在地板上滾動,運動模糊的效果。spa

#include "gltools.h"

GLfloat fLightPos[4] = { -100.0f, 100.0f, 50.0f, 1.0f };
GLfloat fNoLight[] = { 0.0f, 0.0f, 0.0f, 0.0f };
GLfloat fLowLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };
GLfloat fBrightLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };

static GLfloat yRot;

void DrawGround()
{
GLfloat fExtent = 20.0f;
GLfloat y = -0.0f;
GLfloat step = 0.5f;

GLfloat x, z;
int iColor = 0;
glShadeModel(GL_FLAT);
for (x = -fExtent; x <= fExtent; x += step)
{
glBegin(GL_TRIANGLE_STRIP);
for (z = fExtent; z >= -fExtent; z -= step)
{
if ((iColor % 2) == 0)
{
glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
}
else
{
glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
}
glVertex3f(x, y, z);
glVertex3f(x + step, y, z);

iColor++;
}
glEnd();
}
glShadeModel(GL_SMOOTH);

}

void DrawGemometry()
{
glPushMatrix();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawGround();

glColor3f(1.0f, 0.0f, 0.0f);
glTranslatef(0.0f, 0.3f, -3.5f);
glRotatef(-yRot*2.0f, 0.0f, 1.0f, 0.0f);
glTranslatef(1.0f, 0.0f, 0.0f);
glutSolidSphere(0.1f, 17, 13);
glPopMatrix();
}

void RenderScene()
{
yRot = 35.0f;
GLfloat pass = 10.0f;
for (int i = 0; i < 10; ++i)
{
yRot += 0.75f;
DrawGemometry();

//複製到累積緩衝區
if (i == 0)
{
glAccum(GL_LOAD, 0.5f);
}
else
{
//累加到累積緩衝區
glAccum(GL_ACCUM, (0.5f * 1 / pass));
}
}

glAccum(GL_RETURN, 1.0f);
glutSwapBuffers();
}

void ChangeSize(GLsizei w, GLsizei h)
{
if (h == 0)
h = 1;

glViewport(0, 0, w, h);

GLfloat faspect = (GLfloat)w/(GLfloat)h;


glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluPerspective(35.0f, faspect, 1.0f, 50.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, -0.4f, 0.0f);

glutPostRedisplay();
}

void SetupRC()
{
glClearColor(0.25f, 0.25f, 0.25f, 1.0f);

glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);


//設置光照
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, fNoLight);
glLightfv(GL_LIGHT0, GL_AMBIENT, fLowLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, fBrightLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, fBrightLight);
glLightfv(GL_LIGHT0, GL_POSITION, fLightPos);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);


//開啓顏色追蹤
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMateriali(GL_FRONT, GL_SHININESS, 128);
}


int main(int args, char **argv)
{
glutInit(&args, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_ACCUM);
glutInitWindowSize(800, 600);
glutCreateWindow("motion blur");

glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);

SetupRC();

glutMainLoop();
return 0;
}

DrawGeometry函數繪製了場景中的全部幾何圖元。在RenderScene中反覆調用這個函數,並把結果累積到累積緩衝區中。在最後,拷貝回到顏色緩衝區,而後glutSwapBuffers顯示到屏幕上:.net

image

其餘顏色操做

顏色掩碼

在計算後的最終顏色將要寫入到顏色緩衝區時,OpenGL容許你經過glColorMask函數來屏蔽掉其中的一個或多個通道值。code

void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);內存

參數分別表明紅、綠、藍、alpha通道。當傳的參數是GL_TRUE時,表示容許往這個通道的寫值,若是爲GL_FALSE則阻止往該通道寫值。ci

顏色邏輯操做

許多2D的圖形API容許源顏色和目的顏色進行邏輯操做。OpenGL也支持這種操做:get

void glLogicOp(GLenum op);

還須要經過glEnable(GL_COLOR_LOGIC_OP);來開啓。OpenGL在默認狀況下是關閉的。關閉操做是相應的glDisable

op容許的操做以下表:

參數值 操做
GL_CLEAR 0
GL_AND s & d
GL_AND_REVERSE s & ~d
GL_COPY s
GL_AND_INVERTED ~s & d
NOOP d
XOR s xor d
OR s | d
NOR ~(s | d)
GL_EQUIV ~(s xor d)
GL_OR_REVERSE s | ~d
GL_COPY_INVERTED ~s
GL_OR_INVERTED ~s | d
GL_NAND ~(s & d)
SET all 1s

Alpha 測試

Alpha測試容許你告訴OpenGL那些在Alpha測試不經過的輸入片斷將被廢棄。那些被廢棄的片斷不會寫入到顏色緩衝區,深度緩衝區,模板緩衝區和累積緩衝區中。那些alpha值很低的片斷多是不可見的,所以咱們能夠過濾掉它,不寫入到緩衝區中,能夠提升性能。

alpha測試值和比較函數能夠經過glAlphaFunc指定:

void glAlphaFunc(GLenum func, GLclampf ref);

ref的取值範圍爲[0.0, 1.0].能夠指定的比較方式以下表:

比較方式 描述
GL_NEVER 永遠不經過
GL_ALWAYS 一直經過
GL_LESS 小於ref
GL_LEQUAL 小於等於ref
GL_EQUAL 等於ref
GL_GEQUAL 大於等於ref
GL_GREATER 大於ref
GL_NOTEQUAL 不等於ref

行爲與glDepthFunc函數類似。能夠經過glEnable/glDisable來開啓和關閉alpha測試,參數值是GL_ALPHA_TEST。

抖動

抖動容許只有少許離散顏色的顯示系統來模擬更寬範圍的顏色。例如,灰色能夠經過白點和黑點的混合來模擬。白點多於黑點呈現淺灰色,黑點多於白點呈現深灰色。這種技巧對於只支持8位和16位的顯示系統很是有用。抖動的效果能夠大幅度地改善低端顏色系統的圖像質量。在默認狀況下,抖動是打開的。能夠經過glEnable(GL_DITHER)/glDisable(GL_DITHER)來打開或關閉它。在高顏色分辨率的顯示系統中,OpenGL的實現可能不須要抖動,會禁用抖動來避免性能的開銷。

相關文章
相關標籤/搜索