生活随笔
收集整理的這篇文章主要介紹了
使用OpenGL Shader实现放大镜效果
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
使用OpenGL Shader實現放大鏡效果
2014年3月16日renjihe
周末閑來無事,想玩玩OpenGL Shader,想想就實現一個放大鏡效果的Shader吧。
著色器可以指定放大鏡位置、半徑、及放大部數,我實現是在片段著色中使用向后映射的雙線性插值的方式對當前片段顏色進行插值,而頂點著色器什么都不做。
先來看一下頂點著色器。
| 1 | uniform?float?texture_id;//當前使用的紋理的ID |
| 5 | ????gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;//輸出默認頂點位置 |
| 6 | ????gl_FrontColor = gl_Color; |
| 7 | ????gl_TexCoord[texture_id] = gl_TextureMatrix[texture_id] * gl_MultiTexCoord0;//輸出當前頂點對應的紋理坐標。 |
再來看一下片段著色器。
| 01 | uniform vec2? in_circle_pos;//從客戶端傳入的放大鏡圓心位置 |
| 02 | uniform?float?in_circle_radius;//從客戶端傳入的放大鏡圓半徑 |
| 03 | uniform?float?in_zoom_times;//從客戶端傳入的放大鏡放大倍數 |
| 05 | uniform?float?imageWidth;//從客戶端傳入的圖片寬數據 |
| 06 | uniform?float?imageHeight;//從客戶端傳入的圖片高數據 |
| 08 | uniform?float?texture_id;//從客戶端傳入的紋理ID數據 |
| 10 | uniform sampler2D textureSampler;//從客戶端傳入的采樣器ID |
| 12 | vec2 transForTexPosition(vec2 pos) |
| 14 | ????return?vec2((float)pos.x/imageWidth, (float)pos.y/imageHeight); |
| 17 | float?getDistance(vec2 pos_src, vec2 pos_dist) |
| 19 | ????float?quadratic_sum =?pow((pos_src.x - pos_dist.x), 2) +?pow((pos_src.y - pos_dist.y), 2); |
| 20 | ????return?sqrt(quadratic_sum); |
| 23 | vec2 getZoomPosition() |
| 25 | ????float?zoom_x = (float)(gl_FragCoord.x - in_circle_pos.x) / in_zoom_times; |
| 26 | ????float?zoom_y = (float)(gl_FragCoord.y - in_circle_pos.y) / in_zoom_times; |
| 27 | ????return?vec2((float)in_circle_pos.x + zoom_x, (float)in_circle_pos.y - zoom_y); |
| 30 | vec4 getColor()//雙線性插值采樣 |
| 32 | ????vec2 pos = getZoomPosition(); |
| 34 | ????float?_x =?floor(pos.x); |
| 35 | ????float?_y =?floor(pos.y); |
| 37 | ????float?u = pos.x - _x; |
| 38 | ????float?v = pos.y - _y; |
| 40 | ????vec4 data_00 = texture2D(textureSampler, transForTexPosition(vec2(_x, _y))); |
| 41 | ????vec4 data_01 = texture2D(textureSampler, transForTexPosition(vec2(_x, _y + 1))); |
| 42 | ????vec4 data_10 = texture2D(textureSampler, transForTexPosition(vec2(_x + 1, _y))); |
| 43 | ????vec4 data_11 = texture2D(textureSampler, transForTexPosition(vec2(_x + 1, _y + 1))); |
| 45 | ????return?(1 - u) * (1 - v) * data_00 + (1 - u) * v * data_01 + u * (1 - v) * data_10 + u * v * data_11; |
| 50 | ????vec2 frag_pos = vec2(gl_FragCoord.x, gl_FragCoord.y); |
| 51 | ????//若當前片段位置距放大鏡圓心距離大于圓半徑時,直接從紋理中采樣輸出片段顏色 |
| 52 | ????if?(getDistance(in_circle_pos, frag_pos) > in_circle_radius) |
| 53 | ????????gl_FragColor = texture2D(textureSampler, gl_TexCoord[texture_id].st); |
| 54 | ????else//距離小于半徑的片段,二次線性插值獲得顔色。 |
| 55 | ????????gl_FragColor = getColor(); |
再來看看一看客戶端主要操作。
從編譯的Shader程序中獲取變量,用于后續操作。
| 1 | m_circle_pos = glGetUniformLocation(m_program,?"in_circle_pos"); |
| 2 | m_circle_radius = glGetUniformLocation(m_program,?"in_circle_radius"); |
| 3 | m_zoom_times = glGetUniformLocation(m_program,?"in_zoom_times"); |
| 5 | m_image_width = glGetUniformLocation(m_program,?"imageWidth"); |
| 6 | m_image_height = glGetUniformLocation(m_program,?"imageHeight"); |
| 7 | m_texture_sampler = glGetUniformLocation(m_program,?"textureSampler"); |
| 8 | m_texture_id? = glGetUniformLocation(m_program,?"texture_id"); |
對上面獲取的變量賦值。
| 1 | glUniform2f(m_circle_pos, circle_pos.x(), circle_pos.y()); |
| 2 | glUniform1f(m_circle_radius, (float)100.0); |
| 3 | glUniform1f(m_zoom_times, (float)2.0); |
| 5 | glUniform1f(m_image_width, (float)this->width); |
| 6 | glUniform1f(m_image_height, (float)this->height); |
| 8 | glUniform1i(m_texture_sampler, kTexture); |
| 9 | glUniform1i(m_texture_id, kTexture); |
畫圖。
| 1 | glBindTexture(GL_TEXTURE_2D, m_textures[kTexture]); |
| 4 | ????glTexCoord2f(0.0, 0.0);glVertex3f(-this->width/2,?this->height/2, 0.0); |
| 5 | ????glTexCoord2f(0.0, 1.0);glVertex3f(-this->width/2, -this->height/2, 0.0); |
| 6 | ????glTexCoord2f(1.0, 1.0);glVertex3f(this->width/2, -this->height/2, 0.0); |
| 7 | ????glTexCoord2f(1.0, 0.0);glVertex3f(this->width/2,?this->height/2, 0.0); |
最終效果如下:
作者:renjihe 出處:http://www.renjihe.com
本站所有文章均是原創,版權歸本站所有。歡迎轉載,但未經同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利.
總結
以上是生活随笔為你收集整理的使用OpenGL Shader实现放大镜效果的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。