OpenGL之顏色

OpenGL之基礎(chǔ)
OpenGL之繪制簡單形狀

平滑著色

實現(xiàn)矩形中間亮,邊緣暗淡的效果艘蹋,使用三角形扇繪制矩形锄贼,并給頂點(diǎn)添加顏色信息

三角形扇

如下圖所示,如果用四個三角形組成矩形女阀,有很多頂點(diǎn)是可以共用的宅荤,三角形扇就是一種共用頂點(diǎn)的方式


image-20211220220703248.png

一個三角形扇以一個中心頂點(diǎn)作為起始,使用相鄰的兩個頂點(diǎn)創(chuàng)建第一個三角形浸策,接下來的每個頂點(diǎn)都會創(chuàng)建一個三角形冯键,圍繞起始的中心點(diǎn)按扇形展開。為了使這個扇形閉合庸汗,我們只需要在最后重復(fù)第二個點(diǎn)


image-20211220221031080.png

添加顏色屬性

給頂點(diǎn)數(shù)組增加顏色屬性

// 頂點(diǎn)數(shù)據(jù)
float[] vertex = new float[]{
        // 位置(x,y)+顏色(r,g,b)信息
        0f, 0f, 0.9f, 0.9f, 0.9f,
        -0.8f, -0.8f, 0.6f, 0.6f, 0.6f,
        0.8f, -0.8f, 0.6f, 0.6f, 0.6f,
        0.8f, 0.8f, 0.6f, 0.6f, 0.6f,
        -0.8f, 0.8f, 0.6f, 0.6f, 0.6f,
        -0.8f, -0.8f, 0.6f, 0.6f, 0.6f,

        -0.8f, 0f, 1f, 0f, 0f,
        0.8f, 0f, 1f, 0f, 0f,

        0f, -0.5f, 0f, 1f, 0f,
        0f, 0.5f, 0f, 0f, 1f
};

OpenGL中的一種顏色有4個分量(紅色惫确、綠色、藍(lán)色和阿爾法)蚯舱,但不必指定所有分量的值改化,不像uniform 必須傳入4個分量,OpenGL 會用默認(rèn)值替換 attribute 中未指定值的分量:前三個分量會被設(shè)為0枉昏,而最后一個分量會被設(shè)為1

我這里的顏色分量是隨意寫的陈肛,可以使用下面的方法獲取顏色分量

int parsedColor = Color.parseColor("#874326");
float red = Color.red(parsedColor) / 255f;
float green = Color.green(parsedColor) / 255f;
float blue = Color.blue(parsedColor) / 255f;

給著色器增加顏色屬性

頂點(diǎn)著色器
attribute vec4 a_Position;
attribute vec4 a_Color;

varying vec4 v_Color;
void main(){
    v_Color=a_Color;
    gl_Position=a_Position;
    gl_PointSize=10.0;
}

加入了一個新的 attribute 類型的 a_Color,也加入了一個 varying 類型的 v_Color

varying 是一個特殊的變量類型兄裂,它會把給它的那些值進(jìn)行混合句旱,并把這些混合后的值發(fā)送給片段著色器

例如:兩個頂點(diǎn) A 和 B 構(gòu)成一條直線,并為這條直線生成片段懦窘,如果頂點(diǎn) A 的 a_Color 是紅色前翎,且頂點(diǎn) B 的 a_Color 是綠色,通過把 a_Color 賦值給 v_Color畅涂,來告訴 OpenGL 我們需要每個片段都接收一個混合后的顏色港华,接近頂點(diǎn)0的片段,混合后的顏色顯得更紅午衰,而越接近頂點(diǎn)1的片段立宜,顏色就會越綠。

片段著色器
precision mediump float;
varying vec4 v_Color;
void main(){
    gl_FragColor=v_Color;
}

用 varying 類型的變量 v_Color 替換了原來代碼中的 uniform 類型的 u_Color臊岸,如果那個片段屬于一條直線橙数,那么 OpenGL 就會用構(gòu)成那條直線的兩個頂點(diǎn)計算其混合后的顏色,如果那個片段屬于一個三角形帅戒,那 OpenGL 就會用構(gòu)成那個三角形的三個頂點(diǎn)計算其混合后的顏色灯帮,然后傳給 v_Color 崖技,而 v_Color 的值又會被賦值給最終的顏色值 gl_FragColor 作為當(dāng)前片段的最終顏色

使用新的顏色屬性渲染

已經(jīng)給數(shù)據(jù)增加了一個顏色屬性,并且更新了頂點(diǎn)和片段著色器钟哥,讓它們使用這個屬性迎献,因此要去掉使用 unifom 傳遞顏色的舊代碼,并告訴 OpenGL 把顏色作為一個頂點(diǎn)屬性讀入

public class MyRenderer implements GLSurfaceView.Renderer {
    private final FloatBuffer mVertexBuffer;
    private Context mContext;
    private int a_color;
    private int a_position;

    public MyRenderer(Context context) {
        mContext = context;
        // 頂點(diǎn)數(shù)據(jù)
        float[] vertex = new float[]{
                // 位置(x,y)+顏色(r,g,b)信息
                0f, 0f, 0.9f, 0.9f, 0.9f,
                -0.8f, -0.8f, 0.6f, 0.6f, 0.6f,
                0.8f, -0.8f, 0.6f, 0.6f, 0.6f,
                0.8f, 0.8f, 0.6f, 0.6f, 0.6f,
                -0.8f, 0.8f, 0.6f, 0.6f, 0.6f,
                -0.8f, -0.8f, 0.6f, 0.6f, 0.6f,

                -0.8f, 0f, 1f, 0f, 0f,
                0.8f, 0f, 1f, 0f, 0f,

                0f, -0.5f, 0f, 1f, 0f,
                0f, 0.5f, 0f, 0f, 1f
        };
        mVertexBuffer = ByteBuffer.allocateDirect(vertex.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(vertex);
        mVertexBuffer.position(0);
    }

    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
        glClearColor(1f, 1f, 1f, 1f);

        int vertexShader = ShaderHelper.compileVertexShader(mContext, R.raw.gradient2_vertex);
        int fragmentShader = ShaderHelper.compileFragmentShader(mContext, R.raw.gradient2_fragment);
        int program = ProgramHelper.getProgram(vertexShader, fragmentShader);
        glUseProgram(program);

        a_color = glGetAttribLocation(program, "a_Color");
        a_position = glGetAttribLocation(program, "a_Position");

        // 調(diào)節(jié)緩沖區(qū)的指針腻贰,從第一個數(shù)據(jù)讀
        mVertexBuffer.position(0);
        // STRIDE 傳入一個頂點(diǎn)的所有屬性占用的 Float 個數(shù)吁恍,表示下一個頂點(diǎn)數(shù)據(jù)從哪里開始讀
        glVertexAttribPointer(a_position, POSITION_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, mVertexBuffer);
        // 使能頂點(diǎn)屬性數(shù)組,每個attribute都要調(diào)用一次播演,相當(dāng)于一個開關(guān)冀瓦,調(diào)用后,OpenGL才知道到哪里找到屬性對應(yīng)的數(shù)據(jù)
        glEnableVertexAttribArray(a_position);

        // 調(diào)節(jié)緩沖區(qū)的指針写烤,從表示顏色的位置開始讀
        mVertexBuffer.position(POSITION_COMPONENT_COUNT);
        glVertexAttribPointer(a_color, COLOR_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, mVertexBuffer);
        glEnableVertexAttribArray(a_color);
    }

    @Override
    public void onSurfaceChanged(GL10 gl10, int width, int height) {
        glViewport(0, 0, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl10) {
        glClear(GL_COLOR_BUFFER_BIT);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 6);

        glDrawArrays(GL_LINES, 6, 2);

        glDrawArrays(GL_POINTS, 8, 1);
        glDrawArrays(GL_POINTS, 9, 1);
    }
}

效果圖

image-20211220220504459.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翼闽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子顶霞,更是在濱河造成了極大的恐慌肄程,老刑警劉巖锣吼,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件选浑,死亡現(xiàn)場離奇詭異,居然都是意外死亡玄叠,警方通過查閱死者的電腦和手機(jī)古徒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來读恃,“玉大人隧膘,你說我怎么就攤上這事∷卤梗” “怎么了疹吃?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長西雀。 經(jīng)常有香客問我萨驶,道長,這世上最難降的妖魔是什么艇肴? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任腔呜,我火速辦了婚禮,結(jié)果婚禮上再悼,老公的妹妹穿的比我還像新娘核畴。我一直安慰自己,他們只是感情好冲九,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布谤草。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丑孩。 梳的紋絲不亂的頭發(fā)上泳炉,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天,我揣著相機(jī)與錄音嚎杨,去河邊找鬼花鹅。 笑死,一個胖子當(dāng)著我的面吹牛枫浙,可吹牛的內(nèi)容都是我干的刨肃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼箩帚,長吁一口氣:“原來是場噩夢啊……” “哼真友!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起紧帕,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤盔然,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后是嗜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愈案,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年鹅搪,在試婚紗的時候發(fā)現(xiàn)自己被綠了站绪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡丽柿,死狀恐怖恢准,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情甫题,我是刑警寧澤馁筐,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站坠非,受9級特大地震影響敏沉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜麻顶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一赦抖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辅肾,春花似錦队萤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舍杜。三九已至,卻和暖如春赵辕,著一層夾襖步出監(jiān)牢的瞬間既绩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工还惠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饲握,地道東北人。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓蚕键,卻偏偏與公主長得像救欧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子锣光,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容