출처 : http://skyzerotiger.com/74


OpenGLES 를 다루다 보면 가장 큰 문제가 

Matrix와 관련된 함수가 없다는 것인데


친절하게 만들어 주신 분의 블로그를 찾았다 ㅠㅠ 



감사히 사용해야겠다. 

(위 블로그로 이동하시면 해당 소스가 있습니다)

'Programmer의 텅빈 공간 > OpenGL/GLSL' 카테고리의 다른 글

OpenGLES 에서의 gluLookAt  (0) 2015.01.20
토파즈 필터 구현시 도움이 될만한 논문  (0) 2014.07.11
Color Curves Shader  (0) 2014.06.13
Kuwahara Effect  (0) 2014.06.11
Edge Effect Shader  (0) 2014.06.11

출처 : http://iphonedevelopment.blogspot.kr/2008/12/glulookat.html




 OpenGL에서 사용되던 카메라 시점을 설정해 주기 위한 


glLookAt이 OpenGLES에서는 제공되지 않기 때문에 찾던 중 발견함.


역시... 해외 능력자들은 대단하다 ㅠㅠb



gluLookAt.h

/*
* gluLookAt.h
*
* This is a modified version of the function of the same name from
* the Mesa3D project ( http://mesa3d.org/ ), which is licensed
* under the MIT license, which allows use, modification, and
* redistribution
*
* In order to work under OpenGL ES, all instances of GLdouble
* had to be changed to GLfloat, and all "d" function calls had
* to be changed to the "f" versions.
*
* Original developer's comments have been left in place.
*
* Out of respect for the original authors, this is licensed under
* the Mesa (MIT) license. Original license follows:
*
* -----------------------------------------------------------------------
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.

* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/

#import <Foundation/Foundation.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>

void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
GLfloat centerx, GLfloat centery, GLfloat centerz,
GLfloat upx, GLfloat upy, GLfloat upz);




gluLookAt.c

/*
* gluLookAt.c
*/


#include "gluLookAt.h"

void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
GLfloat centerx, GLfloat centery, GLfloat centerz,
GLfloat upx, GLfloat upy, GLfloat upz)
{
GLfloat m[16];
GLfloat x[3], y[3], z[3];
GLfloat mag;

/* Make rotation matrix */

/* Z vector */
z[0] = eyex - centerx;
z[1] = eyey - centery;
z[2] = eyez - centerz;
mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
if (mag) { /* mpichler, 19950515 */
z[0] /= mag;
z[1] /= mag;
z[2] /= mag;
}

/* Y vector */
y[0] = upx;
y[1] = upy;
y[2] = upz;

/* X vector = Y cross Z */
x[0] = y[1] * z[2] - y[2] * z[1];
x[1] = -y[0] * z[2] + y[2] * z[0];
x[2] = y[0] * z[1] - y[1] * z[0];

/* Recompute Y = Z cross X */
y[0] = z[1] * x[2] - z[2] * x[1];
y[1] = -z[0] * x[2] + z[2] * x[0];
y[2] = z[0] * x[1] - z[1] * x[0];

/* mpichler, 19950515 */
/* cross product gives area of parallelogram, which is < 1.0 for
* non-perpendicular unit-length vectors; so normalize x, y here
*/


mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
if (mag) {
x[0] /= mag;
x[1] /= mag;
x[2] /= mag;
}

mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
if (mag) {
y[0] /= mag;
y[1] /= mag;
y[2] /= mag;
}

#define M(row,col) m[col*4+row]
M(0, 0) = x[0];
M(0, 1) = x[1];
M(0, 2) = x[2];
M(0, 3) = 0.0;
M(1, 0) = y[0];
M(1, 1) = y[1];
M(1, 2) = y[2];
M(1, 3) = 0.0;
M(2, 0) = z[0];
M(2, 1) = z[1];
M(2, 2) = z[2];
M(2, 3) = 0.0;
M(3, 0) = 0.0;
M(3, 1) = 0.0;
M(3, 2) = 0.0;
M(3, 3) = 1.0;
#undef M
glMultMatrixf(m);

/* Translate Eye to Origin */
glTranslatef(-eyex, -eyey, -eyez);

}


'Programmer의 텅빈 공간 > OpenGL/GLSL' 카테고리의 다른 글

OpenGLES에서 Matrix 기능 사용하기  (0) 2015.01.20
토파즈 필터 구현시 도움이 될만한 논문  (0) 2014.07.11
Color Curves Shader  (0) 2014.06.13
Kuwahara Effect  (0) 2014.06.11
Edge Effect Shader  (0) 2014.06.11


토파즈 필터를 알게되곤 구현욕구가 좀 생겨서 공부 좀 하려 합니당 ! 


그에 필요한 준비과정으로 읽어봐야 할 논문 !!



kang_eg2011.pdf


'Programmer의 텅빈 공간 > OpenGL/GLSL' 카테고리의 다른 글

OpenGLES에서 Matrix 기능 사용하기  (0) 2015.01.20
OpenGLES 에서의 gluLookAt  (0) 2015.01.20
Color Curves Shader  (0) 2014.06.13
Kuwahara Effect  (0) 2014.06.11
Edge Effect Shader  (0) 2014.06.11


참고 : http://blog.naver.com/soulcriboh/150168261078


포토샵을 보면 색상 변화를 주기 위해 사용하는 기능으로 Curves가 있죠.



이 기능 말입니다 ! 


이 기능을 구현해 보았습니다. 


Curves의 기본 내용은 


그래프의 x 축 input 값이 들어가면 사용자가 지정한 그래프 에 따라 y축 값이 달라지는데 


이 y축 값을 output 값으로 색상을 변경해 출력하는 겁니다. 


Curves의 알고리즘을 알았으니 어떻게 할까 고민을 하다가


선배의 도움을 받아 그래프를 수정할 좌표 점을 2개 이상 (시작점, 끝점 포함) 입력하면


입력된 좌표를 모두 지나는 그래프 식을 구하는 방법을 사용하기로 했습니다.


그 그래프로 256*1 크기의 texture map을 생성하고 그 texture map을 이용하여 색상 값을


변경해서 출력해줍니다 ! 



1) 받은 좌표를 이용해 다항식을 구해야 하는데 방법으로는 라그랑지(lagrange) 보간법을

사용하기로 함

자세한 라그랑지 보간법 설명과 코드의 설명은 위에 적은 블로그에서 확인해 주세요 !!

(여담이지만... 코드를 이용하긴 했는데 이해를 완벽하게 하지는 못했어요 ㅠㅠ 

역시 수학은 잘하고 봐야함.......)


사용한 블로그에서의 코드는 구한 다항식을 출력만 해주는데 전 그 수식을 이용한

값을 사용해야 해서 약간 수정해서 사용했습니다.



2) 생성한 texture map과 해당 이미지를 쉐이더로 넘겨서 curves를 적용해 줍니다.




적용 결과 


입력한 좌표

(0,0) , (0.325, 0.25), (0.625,0.75), (1,1)


 

원본

 

결과

















참고로 texture map을 만드는 lagrange 보간법에서 소수점은 정확한 계산을 하지 못합니다.

그래서 전 좌표 입력은 보기 편하게 0 - 1사이값으로 받지만 

받자마자 0 - 255 값으로 변경한 후에 계산해 줍니다 !


포토샵이랑 비교했을 때 정확히 일치하는 결과는 아니지만 비슷하게 출력됩니다 !

출처 : https://code.google.com/p/gpuakf/source/browse/glsl/kuwahara.glsl



출처에 있는 코드를 적용한 결과

<원본>





LoG를 통해 구현했던 Edge Effect는 아무래도 커널로 변환하는 과정이 완벽하지 않아서 인지

영 노이즈가 많이 생기길래 .. 간단하게 Canny Edge Effect 구현하는 코드를 구함


출처 :

edge.pdf


구현 방법은 간단하게 

1) 원본 이미지를 흑백 변환해주고

2) 흑백 변환된 이미지에 가우시안 블러를 적용하여 엣지를 구할 이미지 생성하고

3) 블러까지 적용된 이미지로 Gradient를 생성해 주면 끝 !


아래 코드는 위의 glsl 코드를 약간 변형하여 엣지의 두께 및 색상을 조절할 수 있는 코드 !


Edge Effect Shader


precision mediump  float;


uniform sampler2D uTexID0;           // 흑백 블러 이미지

varying vec2 vTexCoord;

uniform vec2 uTexel;             // 텍셀

uniform float               uOffset;             // 엣지 두께

uniform float uThreshold;       // 임계치

uniform vec4 uColor;             // 엣지 색상


void main()

{

    vec2 pixelRight   = vTexCoord + vec2(uTexel.x*uOffset,0.0),

         pixelLeft    = vTexCoord + vec2(-uTexel.x*uOffset,0.0),

         pixelTop     = vTexCoord + vec2(0.0,uTexel.y*uOffset),

         pixelBottom  = vTexCoord + vec2(0.0,-uTexel.y*uOffset);


    vec2 gradient = vec2(length(texture2D(uTexID0,pixelRight).xyz

                         - texture2D(uTexID0,pixelLeft).xyz),

                         length(texture2D(uTexID0,pixelTop).xyz

                         - texture2D(uTexID0,pixelBottom).xyz));

    // 배경은 흰색 엣지는 입력받은 색상으로 그려줌

    gl_FragColor =  mix( vec4(1.0,1.0,1.0,1.0), uColor, length(gradient)-uThreshold);

  }

 

'Programmer의 텅빈 공간 > OpenGL/GLSL' 카테고리의 다른 글

Color Curves Shader  (0) 2014.06.13
Kuwahara Effect  (0) 2014.06.11
LoG : Laplacian of Gaussian edge detection  (0) 2014.05.29
unsharp mask 를 이용한 sharpen filter  (0) 2014.05.27
Emboss shader  (0) 2014.05.21


참고 : http://homepages.inf.ed.ac.uk/rbf/HIPR2/log.htm

         http://fourier.eng.hmc.edu/e161/lectures/gradient/node9.html


LoG는 이미지의 외곽선을 추출하기 위해 

이미지에 가우시안 블러를 적용하고 블러가 적용된 이미지에 라플라시안 필터를 적용하여

라플라시안보다 노이즈가 적은 외곽선을 추출하는 기법.


가우시안 블러 수식 

라플라시안 필터 수식

LoG 수식


수식에 필요한 값은 가운데 좌표가 0인 x, y 값과 가우시안 표준편차인 σ 값이 필요하다.

이 LoG 수식을 그래프로 표현한 것이 아래 그림이다. 



LoG값으로 커널을 생성할 수 있는데 커널을 생성하기 위해선 비례식이 필요하다. 

커널의 사이즈에 따라 비례식이 변하게 되는데 기준은 LoG(0,0)이다. 

LoG(0,0)의 경우 x와 y 값이 모두 0이기 때문에 결국 모두 같은 값으로 계산된다.

LoG(0,0) = -1/(πσ^4)

커널의 가운데 값이 가장 작은 값으로 존재해야 하므로 커널의 비례식은 아래와 같이 표현 할 수 있다.

α : -10*Radius = LoG(x,y) : LoG(0,0)

커널 반지름 : Radius

LoG(0,0)과 매치되는 -10*Radius의 경우는 .. 솔직히 아래 커널 값을 보고 이정도면 맞겠구나 하고 

때려 맞춰 넣은 값이다. 저 LoG 식에서 커널 값을 도출해 내는 정확한 방법을 찾고 있지만... 검색 능력이 딸리는 것인지 찾기 못했다 ㅠㅠ.. 

여튼 저 비례식을 이용하면 아래와 비슷한 커널값을 도출해 낼 수 있다.

이 커널 값은 커널 반지름(반경)은 4이고 가우시안 표준편차(σ)는 1.4를 적용하였을 때 커널 값이다. 


LoG vertex Shader

precision highp  float;

attribute vec3 aVertex;

attribute vec2 aTexCoord;

varying vec2 vTexCoord;

void main(void)

{

vTexCoord = vec2(aTexCoord);

gl_Position = vec4(aVertex, 1);

}


LoG frag Shader

uniform sampler2D uTexID0; // 흑백처리된 이미지

varying vec2 vTexCoord; 

uniform float uScale; //가우시안 표준편차(σ)

uniform vec2 uTexel; //Texel size

uniform float               uOffset; //커널 반지름(Radius)

uniform float uStrength; //임계치(Threshold)

 

void main() 

{

    float twoScale2Recip = 1.0 / (2.0 * uScale * uScale);

    float PiScale4Recip = 1. / (3.141592*pow(uScale,4.));

    vec2 pos;

    vec4 texValue;

    vec4 totalTex = vec4(0.,0.,0.,0.);

    float LoGValue;

    float totalLoG = 0.;

    for(pos.x = -uOffset; pos.x<=uOffset; pos.x += 1.){

      for(pos.y = -uOffset; pos.y<=uOffset; pos.y += 1.){

       // LoG 수식 적용

       LoGValue = -PiScale4Recip*(1.-((pow(pos.x,2.)+pow(pos.y,2.))*twoScale2Recip))

                   * exp(-((pow(pos.x,2.)+pow(pos.y,2.))*twoScale2Recip));

       // LoG의 비례식 적용

       LoGValue = (LoGValue*(uOffset*-10))/-PiScale4Recip;

       texValue= texture2D(uTexID0, vTexCoord + vec2(pos.x * uTexel.x, pos.y * uTexel.y))

                 * LoGValue;

       totalTex += texValue;

       totalLoG += LoGValue; // LoG의 모든 값의 합은 0이 되어야 함

                                       // 비례식이 정확하지 않아 모든 합이 0이 되지는 않음 ㅠㅠ

      }

    }

    if(uStrength == 0) //임계값이 없으면 그냥 출력

      gl_FragColor = 1-totalTex; //엣지를 검정으로 표현하기 위한 반전

    else{

      if(totalTex.r >= uStrength)

        gl_FragColor = vec4(0,0,0,1);

      else

        gl_FragColor = vec4(1,1,1,1);

    }

}


'Programmer의 텅빈 공간 > OpenGL/GLSL' 카테고리의 다른 글

Kuwahara Effect  (0) 2014.06.11
Edge Effect Shader  (0) 2014.06.11
unsharp mask 를 이용한 sharpen filter  (0) 2014.05.27
Emboss shader  (0) 2014.05.21
Mosaic Shader  (0) 2014.05.20


출처 : http://scosco.com.ne.kr/Stereo3DHtml/vr_0004_unsharp.htm


UnSharp Mask Filter

가우시안 필터가 이미지를 부드럽게 만드는 것이라면 UnSharp Mask Filter는 이미지를 날카롭게 만드는 방법이다. 기본적으로 UnSharp는 원본이미지와 Bluring된 원본이미지가 필요하다. 그리고 아래와 같이 연산을 하면 된다. g(x, y) = f(x, y) - f_smooth(x, y) h(x, y) = f(x, y) + g(x, y) f(x, y)는 원본 이미지의 픽셀이고, f_smooth(x, y)는 앞에서 설명한 가우시안 필터를 이용하여 생성해 낸 픽셀이다. g(x, y)는 원본 이미지와 Bluring 이미지를 뺀 값인데 결과적으로 영상의 경계선 부분만 검출된다.


                                       원본                                                                           블러


 경계선결과


저 수식을 그림으로 표현하면 아래와 같다.








결과적으로 Highpass 부분만 남은 (c)를 (a)에 더함으로써 경계선 부분이 선명한 이미지가 출력되었다.
수식을 보면 알겠지만 g(x, y)에 k라는 factor를 두어 영상의 경계선을 더욱더 부각시킬수도 있고
경계선을 없애버릴 수도 있다. k는 일반적으로 0.0f 이상을 사용해야 하지만 음수여도 상관은 없다. 
수정된 공식은 아래와 같다.

h(x, y) = f(x, y) + k * g(x, y)



'Programmer의 텅빈 공간 > OpenGL/GLSL' 카테고리의 다른 글

Edge Effect Shader  (0) 2014.06.11
LoG : Laplacian of Gaussian edge detection  (0) 2014.05.29
Emboss shader  (0) 2014.05.21
Mosaic Shader  (0) 2014.05.20
Hertzman Painterly Rendering  (0) 2014.05.16

출처 : http://littlecheesecake.me/blog/13804700/opengles-shader


이미지 정보를 바탕으로 볼륨감을 주는 Emboss effect 

해당 효과를 적용하기 위한 shader code 정리


Emboss vertex shader

precision highp  float;


attribute vec3 aVertex;

attribute vec2 aTexCoord;

varying vec2 vTexCoord;


void main(void)

{

vTexCoord = vec2(aTexCoord);

gl_Position = vec4(aVertex, 1);

}


Emboss fragment shader


uniform sampler2D uTexID0;

varying vec2 vTexCoord;

uniform vec2 uTexel; //texel size


void main()

{

    vec3 irgb = texture2D(uTexID0, vTexCoord).rgb;

    vec3 texrgb = texture2D(uTexID0, vTexCoord + uTexel).rgb;

    

    vec3 diffs = irgb - texrgb;

    float max = diffs.r;

    if(abs(diffs.g)>abs(max)) max = diffs.g;

    if(abs(diffs.b)>abs(max)) max = diffs.b;

    

    float grayDIFFS = clamp(max + .5, 0., 1.);

    vec3 color = vec3(grayDIFFS, grayDIFFS, grayDIFFS);

    

    gl_FragColor = vec4(color.r-0.5+irgb.r,

                                 color.g-0.5+irgb.g,

                                 color.b-0.5+irgb.b,

                                 1.);


'Programmer의 텅빈 공간 > OpenGL/GLSL' 카테고리의 다른 글

LoG : Laplacian of Gaussian edge detection  (0) 2014.05.29
unsharp mask 를 이용한 sharpen filter  (0) 2014.05.27
Mosaic Shader  (0) 2014.05.20
Hertzman Painterly Rendering  (0) 2014.05.16
embossing & sharpening  (0) 2014.05.12

출처 : http://gmc.yoyogames.com/index.php?showtopic=608626


Mosaic Shader Vertex

precision highp  float;

attribute vec3 aVertex;

attribute vec2 aTexCoord;

varying vec2 vTexCoord;


void main(void)

{

vTexCoord = vec2(aTexCoord);

gl_Position = vec4(aVertex, 1);

}


보시는 것 처럼 vertex 부분은 손댈 곳이 없습니다. 

그냥 shader에 들어온 vertex와 texCoord를 그대로 사용해서 넘겨주시면 됩니다. 


Mosaic Shader Frag

uniform sampler2D uTexID0;

varying vec2 vTexCoord;

uniform vec2 uTexel;  //texel size

uniform float uScale;  //tile size


void main() 

{

float dx = uScale*uTexel.x;

float dy = uScale*uTexel.y;

vec2 coord = vec2(floor(vTexCoord.x/dx)*dx+(dx/2.0),

                    floor(vTexCoord.y/dy)*dy+(dy/2.0));

gl_FragColor = texture2D(uTexID0, coord);

}


frag Shader에 경우 Scale값과 Texel 값으로 모자이크의 범위를 정하고 

해당 좌표의 모자이크 범위를 구해 범위의 중점 색상으로 타일 전체를 칠해줍니다. 



'Programmer의 텅빈 공간 > OpenGL/GLSL' 카테고리의 다른 글

unsharp mask 를 이용한 sharpen filter  (0) 2014.05.27
Emboss shader  (0) 2014.05.21
Hertzman Painterly Rendering  (0) 2014.05.16
embossing & sharpening  (0) 2014.05.12
Gaussian Filter  (0) 2014.05.09

+ Recent posts