SpaceEngine изнутри
Crab Дата: Воскресенье, 24.04.2011, 10:45 | Сообщение # 31
Первооткрыватель
Группа: Модераторы
Российская Федерация
Сообщений: 444
Награды:
1
Статус: Offline
А планируется ли делать генерацию поверхности планет подобно Infinity?
Windows 8 x64 Intel Core2 Duo CPU E7500 2.93GHz. 4 GB RAM. Nvidia GeForce 550Ti 1024mb.
SpaceEngineer Дата: Воскресенье, 24.04.2011, 15:15 | Сообщение # 32
Автор Space Engine
Группа: Администраторы
Российская Федерация
Сообщений: 5547
Награды:
55
Статус: Offline
Crab А чем сейчас планеты в SE принципаильно отличаются? Кроме более низкой детализации.
Crab Дата: Понедельник, 25.04.2011, 16:56 | Сообщение # 33
Первооткрыватель
Группа: Модераторы
Российская Федерация
Сообщений: 444
Награды:
1
Статус: Offline
Низкая детализация, однородные текстуры( В инфинити горы выглядят горами а поля полями) Ну водицу бы ещё красивую.)Добавлено (25.04.2011, 16:56) --------------------------------------------- А извиняюсь я думал что лод +3 это лучшее качество)) а рендеринг воды не помешал бы
Windows 8 x64 Intel Core2 Duo CPU E7500 2.93GHz. 4 GB RAM. Nvidia GeForce 550Ti 1024mb.
SpaceEngineer Дата: Пятница, 06.05.2011, 20:20 | Сообщение # 34
Автор Space Engine
Группа: Администраторы
Российская Федерация
Сообщений: 5547
Награды:
55
Статус: Offline
Я перепутал знак, надо было +3 сделать лучшим, -3 худшим. Воду сделаю, это в TODO списке: http://spaceengine.org/forum/15
Crab Дата: Воскресенье, 08.05.2011, 22:40 | Сообщение # 35
Первооткрыватель
Группа: Модераторы
Российская Федерация
Сообщений: 444
Награды:
1
Статус: Offline
Кстати интересно стало что генерируется на газовых гигантах?
Windows 8 x64 Intel Core2 Duo CPU E7500 2.93GHz. 4 GB RAM. Nvidia GeForce 550Ti 1024mb.
SpaceEngineer Дата: Понедельник, 09.05.2011, 18:01 | Сообщение # 36
Автор Space Engine
Группа: Администраторы
Российская Федерация
Сообщений: 5547
Награды:
55
Статус: Offline
На газовых гигантах - три слоя облаков. Они движутся относительно друг друга, это можно заметить, если ускорить время.
Anton1987ru Дата: Воскресенье, 18.09.2011, 01:54 | Сообщение # 37
Космонавт
Группа: Команда SE
Российская Федерация
Сообщений: 56
Награды:
0
Статус: Offline
Книга SpaceEngineer Я думаю эта книга будет полезна в моделировании ландшафта! Сделайте горный ландшафт более разнообразным , по нескольким алгоритмам в одном блоке, а тот фрактальный алгоритм напоминающий синусоиду конечно хорош для отдалённого сверху участка но не особо реален вблизи и больше подходит для амазонских рек )) просто структура гор с таким фрактальным шумом слишком однородная и "правильная" на тысячи километров одинаковая )) И больше напоминает сетчатую структуру чем реальные цепи гор. Надеюсь понимаете что имею в виду. UDP Вот ещё вам Glsl как пост эффекты
Code
//#define GAMMA 1.10 //#define DOF_ENABLED //#define BLOOM_ENABLED #define AA_ENABLED #define SSAO_ENABLED #define GOD_RAYS //#define CEL_SHADING //#define THERMAL_VISION //#define BW_DREAMS //#define LENS //#define WANT_PIXELS //#define MOVING_BLACKHOLE // LENS Params #define LENS_INRAD 0.18 #define LENS_OUTRAD 0.25 // GOD_RAYS Params #ifdef GOD_RAYS const float GR_DECAY = 0.95; const float GR_DENSITY = 0.5; const float GR_EXPOSURE = 0.2; const int GR_SAMPLES = 32; #endif // CEL_SHADING Params #ifdef CEL_SHADING const float CEL_EDGE_THRESHOLD = 0.25; const float CEL_EDGE_THICKNESS = 1.35; #endif // BLOOM Params #ifdef BLOOM_ENABLED const float BLOOM_STRENGTH = 0.125; #endif //DOF Params #ifdef DOF_ENABLED const float HYPERFOCAL = 4.0; #endif /* ------------------------------------------------------- The standard user should not mess with anything below ------------------------------------------------------- */ uniform sampler2D sampler0; uniform sampler2D sampler1; uniform sampler2D sampler2; uniform sampler2D bgl_RenderedTexture; uniform float displayWidth; uniform float displayHeight; uniform float aspectRatio; uniform float near; uniform float far; uniform vec3 sunPosition; uniform int worldTime; const float INFINITY = 1000.0; float getDepth( vec2 coord ) { float depth = texture2D( sampler1, coord ).x; float depth2 = texture2D( sampler2, coord ).x; if ( depth2 < 1.0 ) { depth = depth2; } if ( depth == 1.0 ) { return INFINITY; } depth = -near / (-1+depth * ((far-near)/far)); //depth = 2.0 * near * far / ( far + near - ( 2.0 * depth - 1.0 ) * ( far - near ) ); //return 2.0 * near * far / ( far + near - ( 2.0 * depth - 1.0 ) * ( far - near ) ); return depth; } #ifdef GOD_RAYS vec2 getDepthGR(vec2 coord) { float depth = texture2D(sampler1, coord).x; float depth2 = texture2D(sampler2, coord).x; float fg = -1.0; if (depth2 < 1.0) { depth = depth2; fg = 1.0; } return vec2(2.0 * near * far / (far + near - (2.0 * depth - 1.0) * (far - near)), fg); } #endif #ifdef SSAO_ENABLED // Stuff only SSAO uses float compareDepths( in float depth1, in float depth2 ) { float aoCap = 0.42; float aoMultiplier = 1000.0; float depthTolerance = 0.0; float aorange = 512.0; // units in space the AO effect extends to (this gets divided by the camera far range float diff = sqrt( clamp( 1.0 - ( depth1 - depth2 ) / ( aorange / ( far - near ) ), 0.0, 1.0 ) ); float ao = min( aoCap, max( 0.0, depth1 - depth2 - depthTolerance ) * aoMultiplier ) * diff; return ao; } vec4 getSSAO() { float depth = getDepth( gl_TexCoord[0].st ); float d; float pw = 1.0 / displayWidth; float ph = 1.0 / displayHeight; float aoCap = 1.0; float ao = 0.0; float aoMultiplier = 5000.0; float depthTolerance = 0.0; float aoscale=1.0; d=getDepth( vec2(gl_TexCoord[0].x+pw,gl_TexCoord[0].y+ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x-pw,gl_TexCoord[0].y+ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x+pw,gl_TexCoord[0].y-ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x-pw,gl_TexCoord[0].y-ph)); ao+=compareDepths(depth,d)/aoscale; pw*=2.0; ph*=2.0; aoMultiplier/=2.0; aoscale*=1.2; d=getDepth( vec2(gl_TexCoord[0].x+pw,gl_TexCoord[0].y+ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x-pw,gl_TexCoord[0].y+ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x+pw,gl_TexCoord[0].y-ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x-pw,gl_TexCoord[0].y-ph)); ao+=compareDepths(depth,d)/aoscale; pw*=2.0; ph*=2.0; aoMultiplier/=2.0; aoscale*=1.2; d=getDepth( vec2(gl_TexCoord[0].x+pw,gl_TexCoord[0].y+ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x-pw,gl_TexCoord[0].y+ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x+pw,gl_TexCoord[0].y-ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x-pw,gl_TexCoord[0].y-ph)); ao+=compareDepths(depth,d)/aoscale; pw*=2.0; ph*=2.0; aoMultiplier/=2.0; aoscale*=1.2; d=getDepth( vec2(gl_TexCoord[0].x+pw,gl_TexCoord[0].y+ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x-pw,gl_TexCoord[0].y+ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x+pw,gl_TexCoord[0].y-ph)); ao+=compareDepths(depth,d)/aoscale; d=getDepth( vec2(gl_TexCoord[0].x-pw,gl_TexCoord[0].y-ph)); ao+=compareDepths(depth,d)/aoscale; ao/=16.0; return vec4(1.1-ao); } #endif #ifdef AA_ENABLED // Stuff only AA uses float expDepth2linearDepth( vec2 coord ) { float depth = texture2D( sampler1, coord ).x; float depth2 = texture2D( sampler2, coord ).x; if ( depth2 < 1.0 ) { depth = depth2; } if ( depth == 1.0 ) { return INFINITY; } return ( 2.0 * near ) / ( far + near - depth * ( far - near ) ); } vec4 getAA() { vec4 newColor = vec4(0.0); float depth = expDepth2linearDepth(gl_TexCoord[0].xy); vec2 aspectCorrection = vec2(1.0, aspectRatio) * 0.005; float offsetx = 0.12 * aspectCorrection.x; float offsety = 0.12 * aspectCorrection.y; float depthThreshold=0.01; if ( abs( depth - expDepth2linearDepth( gl_TexCoord[0].xy + vec2( offsetx, 0 ) ) ) > depthThreshold || abs( depth - expDepth2linearDepth( gl_TexCoord[0].xy + vec2( -offsetx, 0 ) ) ) > depthThreshold || abs( depth - expDepth2linearDepth( gl_TexCoord[0].xy + vec2( 0, offsety ) ) ) > depthThreshold || abs( depth - expDepth2linearDepth( gl_TexCoord[0].xy + vec2( 0, -offsety ) ) ) > depthThreshold ) { newColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(-offsetx, offsety)); newColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(0, offsety)); newColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(offsetx, offsety)); newColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(-offsetx, 0)); newColor += texture2D(sampler0, gl_TexCoord[0].st); newColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(offsetx, 0)); newColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(-offsetx, -offsety)); newColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(0, -offsety)); newColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(offsetx, -offsety)); newColor /= 9.0; } else newColor=texture2D(sampler0, gl_TexCoord[0].st); return newColor; } #endif #ifdef BLOOM_ENABLED // Stuff only bloom uses vec4 getBloom() { vec4 sum = vec4(0); vec2 texcoord = vec2(gl_TexCoord[0]); for( int i = -3; i < 3; i++) { // Lower loop count for performance for ( int j = -3; j < 3; j++ ) { sum += texture2D( bgl_RenderedTexture, texcoord + vec2( j, i ) * 0.004 ) * BLOOM_STRENGTH; } } if (texture2D(bgl_RenderedTexture, texcoord).r < 0.3) { sum = sum*sum*0.012 + texture2D(bgl_RenderedTexture, texcoord); } else { if (texture2D(bgl_RenderedTexture, texcoord).r < 0.5) { sum = sum*sum*0.009 + texture2D(bgl_RenderedTexture, texcoord); } else { sum = sum*sum*0.0075 + texture2D(bgl_RenderedTexture, texcoord); } } return sum; } #endif #ifdef DOF_ENABLED // Stuff only DOF uses float samples = float( 0 ); vec2 space; float getCursorDepth( vec2 coord ) { return 2.0 * near * far / ( far + near - ( 2.0 * texture2D( sampler1, coord ).x - 1.0 ) * ( far - near ) ); } vec4 getSampleWithBoundsCheck(vec2 offset) { vec2 coord = gl_TexCoord[0].st + offset; if (coord.s <= 1.0 && coord.s >= 0.0 && coord.t <= 1.0 && coord.t >= 0.0) { samples += 1.0; return texture2D(sampler0, coord); } else { return vec4(0.0); } } vec4 getBlurredColor() { vec4 blurredColor = vec4( 0.0 ); float depth = getDepth( gl_TexCoord[0].xy ); vec2 aspectCorrection = vec2( 1.0, aspectRatio ) * 0.005; vec2 ac0_4 = 0.4 * aspectCorrection; // 0.4 vec2 ac0_29 = 0.29 * aspectCorrection; // 0.29 vec2 ac0_15 = 0.15 * aspectCorrection; // 0.15 vec2 ac0_37 = 0.37 * aspectCorrection; // 0.37 vec2 lowSpace = gl_TexCoord[0].st; vec2 highSpace = 1.0 - lowSpace; space = vec2( min( lowSpace.s, highSpace.s ), min( lowSpace.t, highSpace.t ) ); if (space.s >= ac0_4.s && space.t >= ac0_4.t) { blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(0.0, ac0_4.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(ac0_4.s, 0.0)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(0.0, -ac0_4.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(-ac0_4.s, 0.0)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(ac0_29.s, -ac0_29.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(ac0_29.s, ac0_29.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(-ac0_29.s, ac0_29.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(-ac0_29.s, -ac0_29.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(ac0_15.s, ac0_37.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(-ac0_37.s, ac0_15.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(ac0_37.s, -ac0_15.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(-ac0_15.s, -ac0_37.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(-ac0_15.s, ac0_37.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(ac0_37.s, ac0_15.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(-ac0_37.s, -ac0_15.t)); blurredColor += texture2D(sampler0, gl_TexCoord[0].st + vec2(ac0_15.s, -ac0_37.t)); blurredColor /= 16.0; } else { blurredColor += getSampleWithBoundsCheck(vec2(0.0, ac0_4.t)); blurredColor += getSampleWithBoundsCheck(vec2(ac0_4.s, 0.0)); blurredColor += getSampleWithBoundsCheck(vec2(0.0, -ac0_4.t)); blurredColor += getSampleWithBoundsCheck(vec2(-ac0_4.s, 0.0)); blurredColor += getSampleWithBoundsCheck(vec2(ac0_29.s, -ac0_29.t)); blurredColor += getSampleWithBoundsCheck(vec2(ac0_29.s, ac0_29.t)); blurredColor += getSampleWithBoundsCheck(vec2(-ac0_29.s, ac0_29.t)); blurredColor += getSampleWithBoundsCheck(vec2(-ac0_29.s, -ac0_29.t)); blurredColor += getSampleWithBoundsCheck(vec2(ac0_15.s, ac0_37.t)); blurredColor += getSampleWithBoundsCheck(vec2(-ac0_37.s, ac0_15.t)); blurredColor += getSampleWithBoundsCheck(vec2(ac0_37.s, -ac0_15.t)); blurredColor += getSampleWithBoundsCheck(vec2(-ac0_15.s, -ac0_37.t)); blurredColor += getSampleWithBoundsCheck(vec2(-ac0_15.s, ac0_37.t)); blurredColor += getSampleWithBoundsCheck(vec2(ac0_37.s, ac0_15.t)); blurredColor += getSampleWithBoundsCheck(vec2(-ac0_37.s, -ac0_15.t)); blurredColor += getSampleWithBoundsCheck(vec2(ac0_15.s, -ac0_37.t)); blurredColor /= samples; } return blurredColor; } #endif #ifdef CEL_SHADING float getEdgeDepth(vec2 coord) { float depth = texture2D( sampler1, coord ).x; float depth2 = texture2D( sampler2, coord ).x; if ( depth2 < 1.0 ) { depth = depth2; } if ( depth == 1.0 ) { return INFINITY; } return depth * near / ( far + ( near - far ) * depth ); } vec4 edgeDetect( vec2 coord ) { vec2 o11 = vec2(1.0, aspectRatio)*CEL_EDGE_THICKNESS/displayWidth; vec4 color = vec4(0.0); float depth = getEdgeDepth(coord); float avg = 0.0; float laplace = 24.0 * depth; float sample; int n = 0; if (depth < INFINITY) { avg += depth; ++n; } for (int i = -2; i <= 2; ++i) { for (int j = -2; j <= 2; ++j) { if (i != 0 || j != 0) { sample = getEdgeDepth(coord + vec2(float( i ) * o11.s, float( j ) * o11.t)); laplace -= sample; if (sample < INFINITY) { ++n; avg += sample; } } } } avg = clamp( avg/ float( n ), 0.0, 1.0); if ( laplace > avg * CEL_EDGE_THRESHOLD ) { color.rgb = mix( vec3( 0.0 ), gl_Fog.color.rgb, 0.75 * avg * avg); color.a = 1.0; } return color; } #endif void main() { vec4 baseColor; #ifdef AA_ENABLED baseColor = getAA(); #else baseColor = texture2D( sampler0, gl_TexCoord[0].st ); #endif #ifdef SSAO_ENABLED vec4 getSSAOdodge = getSSAO(); baseColor *= getSSAOdodge; #endif #ifdef BLOOM_ENABLED baseColor = mix( baseColor, getBloom(), 0.5 ); #endif /* Here we add a second pass to SSAO that will only apply if the user has enabled Bloom. The reason for this, is because the way it's done, Bloom actually mix the render so far with an altered ORIGINAL game frame. This means that the SSAO will get partly overwriten. */ #ifdef SSAO_ENABLED #ifdef BLOOM_ENABLED baseColor *= getSSAOdodge; #endif #endif #ifdef THERMAL_VISION vec2 uv = gl_TexCoord[0].xy; vec3 pixcol = baseColor.rgb; vec3 colors[3]; colors[0] = vec3(0.,0.,1.); colors[1] = vec3(1.,1.,0.); colors[2] = vec3(1.,0.,0.); // float lum = (pixcol.r+pixcol.g+pixcol.b)/3.; float lum = dot(vec3(0.30, 0.59, 0.11), pixcol.rgb); int ix = (lum < 0.5)? 0:1; vec3 tc = mix(colors[ix],colors[ix+1],(lum-float(ix)*0.5)/0.5); baseColor = vec4(tc, 1.0); #endif #ifdef GOD_RAYS float threshold = 0.99 * far; bool foreground = false; vec2 depthGR = getDepthGR(gl_TexCoord[0].st); if ((worldTime < 14000 || worldTime > 22000) && sunPosition.z < 0 && depthGR.x < threshold && depthGR.y < 0.0) { vec2 lightPos = sunPosition.xy / -sunPosition.z; lightPos.y *= aspectRatio; lightPos = (lightPos + 1.0)/2.0; vec2 texCoord = gl_TexCoord[0].st; vec2 delta = (texCoord - lightPos) * GR_DENSITY / float(GR_SAMPLES); float decay = -sunPosition.z / 100.0; vec3 color = vec3(0.0); for (int i = 0; i < GR_SAMPLES; i++) { texCoord -= delta; if (texCoord.x < 0.0 || texCoord.x > 1.0) { if (texCoord.y < 0.0 || texCoord.y > 1.0) { break; } } vec3 sample = vec3(0.0); if (getDepthGR(texCoord).x > threshold) sample = texture2D(sampler0, texCoord).rgb; sample *= decay; if (distance(texCoord, lightPos) > 0.05) sample *= 0.2; color += sample; decay *= GR_DECAY; } baseColor = (baseColor + GR_EXPOSURE * vec4(color, 0.0)); } #endif #ifdef CEL_SHADING vec4 outlineColor = edgeDetect( gl_TexCoord[0].st ); if (outlineColor.a != 0.0) { baseColor.rgb = outlineColor.rgb; } #endif #ifdef DOF_ENABLED float depth = getDepth( gl_TexCoord[0].st ); float cursorDepth = getCursorDepth( vec2( 0.5, 0.5 ) ); if ( depth < cursorDepth ) baseColor = mix( baseColor, getBlurredColor(), clamp(2.0 * ((clamp(cursorDepth, 0.0, HYPERFOCAL) - depth) / (clamp(cursorDepth, 0.0, HYPERFOCAL))), 0.0, 1.0)); else baseColor = mix( baseColor, getBlurredColor(), 1.0 - clamp( ( ( ( cursorDepth * HYPERFOCAL ) / ( HYPERFOCAL - cursorDepth ) ) - ( depth - cursorDepth ) ) / ((cursorDepth * HYPERFOCAL) / (HYPERFOCAL - cursorDepth)), 0.0, 1.0)); #endif #ifdef GAMMA if (baseColor[3] == 0.0) { baseColor = gl_Fog.color; } else { baseColor.rgb = pow(baseColor.rgb, vec3(1.0/GAMMA)); } #endif #ifdef BW_DREAMS vec2 uv3 = gl_TexCoord[0].xy; vec4 c = baseColor; c += texture2D(sampler0, uv3+0.001); c += texture2D(sampler0, uv3+0.003); c += texture2D(sampler0, uv3+0.005); c += texture2D(sampler0, uv3+0.007); // c += texture2D(sampler0, uv3+0.009); // c += texture2D(sampler0, uv3+0.011); c += texture2D(sampler0, uv3-0.001); c += texture2D(sampler0, uv3-0.003); c += texture2D(sampler0, uv3-0.005); c += texture2D(sampler0, uv3-0.007); // c += texture2D(sampler0, uv3-0.009); // c += texture2D(sampler0, uv3-0.011); c.rgb = vec3((c.r+c.g+c.b)/3.0); c = c / 9.5; baseColor = c; #endif #ifdef LENS vec2 lensRadius = vec2(LENS_OUTRAD, LENS_INRAD); vec4 Color = baseColor; float dist = distance(gl_TexCoord[0].xy, vec2(0.5,0.5)); Color.rgb *= smoothstep(lensRadius.x, lensRadius.y, dist); baseColor = Color; #endif #ifdef WANT_PIXELS const float rt_w = 1600.0; const float rt_h = 1600.0; const float pixel_w = 8.0; // 15.0 const float pixel_h = 4.0; // 10.0 vec2 uv2 = gl_TexCoord[0].xy; float dx = pixel_w*(1./rt_w); float dy = pixel_h*(1./rt_h); vec2 coord = vec2(dx*floor(uv2.x/dx), dy*floor(uv2.y/dy)); vec3 tc = texture2D(sampler0, coord).rgb; baseColor = vec4(tc, 1.0); #endif #ifdef MOVING_BLACKHOLE vec2 cen = vec2(0.5,0.5) - gl_TexCoord[0].xy; vec2 mcen = - // delete minus for implosion effect 0.07*log(length(cen))*normalize(cen); // gl_FragColor = texture2D(sampler0, gl_TexCoord[0].xy+mcen); baseColor *= texture2D(sampler0, gl_TexCoord[0].xy+mcen); #endif gl_FragColor = baseColor; }
Шейдерный эффект lens flares пока не нашёл но что-то мне подсказывает что можно обычный блюр в несколько проходов отрендерить сначала уменьшит
Windows 7 x64 Core 2 quad Q8200 2.8 GHz 512mb Geforce 9800GTX+ 10 GB RAM ddr2
Сообщение отредактировал Anton1987ru - Воскресенье, 18.09.2011, 04:51
SpaceEngineer Дата: Воскресенье, 18.09.2011, 02:20 | Сообщение # 38
Автор Space Engine
Группа: Администраторы
Российская Федерация
Сообщений: 5547
Награды:
55
Статус: Offline
У меня есть эта книга. Если было бы так просто сделать то что вы говорите, я бы давно это сделал. По поводу шейдеров - спасибо. Но без сопутствующего кода самой программы или хотя бы пояснений сложно разобраться. Что такое sampler0 - sampler2, в сколько проходов этот шейдер прогонять и т.д.
Anton1987ru Дата: Вторник, 27.09.2011, 05:23 | Сообщение # 39
Космонавт
Группа: Команда SE
Российская Федерация
Сообщений: 56
Награды:
0
Статус: Offline
Вот ещё шейдеры надеюсь подходят вам
Code
uniform sampler2D bgl_DepthTexture; uniform sampler2D bgl_RenderedTexture; uniform sampler2D bgl_LuminanceTexture; uniform float bgl_RenderedTextureWidth; uniform float bgl_RenderedTextureHeight; #define PI 3.14159265 float width = bgl_RenderedTextureWidth; //texture width float height = bgl_RenderedTextureHeight; //texture height float near = 1.0; //Z-near float far = 1000.0; //Z-far int samples = 3; //samples on the first ring (3-7) int rings = 3; //ring count (2-8) vec2 texCoord = gl_TexCoord[0].st; vec2 rand(in vec2 coord) //generating random noise { float noiseX = (fract(sin(dot(coord ,vec2(12.9898,78.233))) * 43758.5453)); float noiseY = (fract(sin(dot(coord ,vec2(12.9898,78.233)*2.0)) * 43758.5453)); return vec2(noiseX,noiseY)*0.004; } float readDepth(in vec2 coord) { return (2.0 * near) / (far + near - texture2D(bgl_DepthTexture, coord ).x * (far-near)); } float compareDepths( in float depth1, in float depth2 ) { float aoCap = 1.0; float aoMultiplier = 100.0; float depthTolerance = 0.0000; float aorange = 60.0;// units in space the AO effect extends to (this gets divided by the camera far range float diff = sqrt(clamp(1.0-(depth1-depth2) / (aorange/(far-near)),0.0,1.0)); float ao = min(aoCap,max(0.0,depth1-depth2-depthTolerance) * aoMultiplier) * diff; return ao; } void main(void) { float depth = readDepth(texCoord); float d; float aspect = width/height; vec2 noise = rand(texCoord); float w = (1.0 / width)/clamp(depth,0.05,1.0)+(noise.x*(1.0-noise.x)); float h = (1.0 / height)/clamp(depth,0.05,1.0)+(noise.y*(1.0-noise.y)); float pw; float ph; float ao; float s; for (int i = -rings ; i < rings; i += 1) { for (int j = -samples ; j < samples; j += 1) { float step = PI*2.0 / (samples*float(i)); pw = (cos(float(j)*step)*float(i)); ph = (sin(float(j)*step)*float(i))*aspect; d = readDepth( vec2(texCoord.s+pw*w,texCoord.t+ph*h)); ao += compareDepths(depth,d); s += 1.0; } } ao /= s; ao = 1.0-ao; vec3 color = texture2D(bgl_RenderedTexture,texCoord).rgb; vec3 luminance = texture2D(bgl_LuminanceTexture,texCoord).rgb; vec3 white = vec3(1.0,1.0,1.0); vec3 black = vec3(0.0,0.0,0.0); vec3 treshold = vec3(0.2,0.2,0.2); luminance = clamp(max(black,luminance-treshold)+max(black,luminance-treshold)+max(black,luminance-treshold),0.0,1.0); gl_FragColor = vec4(color*mix(vec3(ao,ao,ao),white,luminance),1.0); }
Code
uniform sampler2D bgl_RenderedTexture; uniform float retinex; vec4 sample( in vec2 coord ) { return texture2D(bgl_RenderedTexture, coord )*0.5*texture2D(bgl_RenderedTexture, coord )*0.5; } void main(void) { vec4 bloom = vec4(0); int j; int i; for( i= -5 ;i < 5; i++) { for (j = -5; j < 5; j++) { bloom += sample (gl_TexCoord[0].st + vec2(j, i)*0.003) * 0.06; } } vec4 value = texture2D(bgl_RenderedTexture, gl_TexCoord[0].st); vec4 pow_value = pow(value,(bloom*retinex)); gl_FragColor = pow_value*value; }
Code
uniform sampler2D bgl_DepthTexture; uniform sampler2D bgl_RenderedTexture; #define camx 0.8 #define camy 800 uniform float width; uniform float height; int j; int i; vec2 texCoord = gl_TexCoord[0].st; float readDepth( in vec2 coord ) { return (2.0 * camx) / (camy + camx - texture2D(bgl_DepthTexture, coord ).x * (camy - camx)); } float compareDepths( in float depth1, in float depth2 ) { float aoCap = 2.0; float aoMultiplier=100.0; float depthTolerance=0.0000; float aorange = 20.0;// units in space the AO effect extends to (this gets divided by the camera far range float diff = sqrt( clamp(1.0-(depth1-depth2) / (aorange/(camy-camx)),0.0,1.0) ); float ao = min(aoCap,max(0.0,depth1-depth2-depthTolerance) * aoMultiplier) * diff; return ao; } void main(void) { float depth = readDepth( texCoord ); float d; float pw = 1.0 / float(width); float ph = 1.0 / float(height); float aoCap = 2.0; float ao = 5.0; float aoMultiplier=1.0; float depthTolerance = 0.0000; float aoscale=0.7; d=readDepth( vec2(texCoord.s+pw,texCoord.t+ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s-pw,texCoord.t+ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s+pw,texCoord.t-ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s-pw,texCoord.t-ph)); ao+=compareDepths(depth,d)/aoscale; pw*=2.0; ph*=2.0; aoMultiplier/=2.0; aoscale*=1.2; d=readDepth( vec2(texCoord.s+pw,texCoord.t+ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s-pw,texCoord.t+ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s+pw,texCoord.t-ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s-pw,texCoord.t-ph)); ao+=compareDepths(depth,d)/aoscale; pw*=2.0; ph*=2.0; aoMultiplier/=2.0; aoscale*=1.4; d=readDepth( vec2(texCoord.s+pw,texCoord.t+ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s-pw,texCoord.t+ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s+pw,texCoord.t-ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s-pw,texCoord.t-ph)); ao+=compareDepths(depth,d)/aoscale; pw*=2.0; ph*=2.0; aoMultiplier/=2.0; aoscale*=1.6; d=readDepth( vec2(texCoord.s+pw,texCoord.t+ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s-pw,texCoord.t+ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s+pw,texCoord.t-ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s-pw,texCoord.t-ph)); ao+=compareDepths(depth,d)/aoscale; pw*=2.0; ph*=2.0; aoMultiplier/=2.0; aoscale*=1.8; d=readDepth( vec2(texCoord.s+pw,texCoord.t+ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s-pw,texCoord.t+ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s+pw,texCoord.t-ph)); ao+=compareDepths(depth,d)/aoscale; d=readDepth( vec2(texCoord.s-pw,texCoord.t-ph)); ao+=compareDepths(depth,d)/aoscale; ao/=15.0; vec4 finalao = vec4(1.0-ao,1.0-ao,1.0-ao,1.0); finalao = clamp(finalao,0.0,0.7)+0.3; gl_FragColor = finalao * texture2D(bgl_RenderedTexture, texCoord ); gl_FragColor.a = 1.0; }
Code
uniform sampler2D bgl_RenderedTexture; const float amount = 1.0; vec2 texCoord = vec2(gl_TexCoord[0]).st; const vec4 redfilter = vec4(1.0, 0.0, 0.0, 0.0); const vec4 bluegreenfilter = vec4(0.0, 1.0, 0.7, 0.0); void main(void) { vec4 input0 = texture2D(bgl_RenderedTexture, texCoord); vec4 redrecord = input0 * redfilter; vec4 bluegreenrecord = input0 * bluegreenfilter; vec4 rednegative = vec4(redrecord.r); vec4 bluegreennegative = vec4((bluegreenrecord.g + bluegreenrecord.b)/2.0); vec4 redoutput = rednegative * redfilter; vec4 bluegreenoutput = bluegreennegative * bluegreenfilter; // additive 'projection" vec4 result = redoutput + bluegreenoutput; gl_FragColor = vec4(vec3(mix(input0, result, amount).rgb), 1.0); }
Code
uniform sampler2D bgl_RenderedTexture; const float amount = 1.0; vec2 texCoord = vec2(gl_TexCoord[0]).st; const vec4 redfilter = vec4(1.0, 0.0, 0.0, 0.0); const vec4 bluegreenfilter = vec4(0.0, 1.0, 0.7, 0.0); void main(void) { vec4 input0 = texture2D(bgl_RenderedTexture, texCoord); vec4 redrecord = input0 * redfilter; vec4 bluegreenrecord = input0 * bluegreenfilter; vec4 rednegative = vec4(redrecord.r); vec4 bluegreennegative = vec4((bluegreenrecord.g + bluegreenrecord.b)/2.0); vec4 redoutput = rednegative * redfilter; vec4 bluegreenoutput = bluegreennegative * bluegreenfilter; // additive 'projection" vec4 result = redoutput + bluegreenoutput; gl_FragColor = vec4(vec3(mix(input0, result, amount).rgb), 1.0); }
Code
uniform sampler2D bgl_RenderedTexture; const float amount = 1.0; vec2 texCoord = vec2(gl_TexCoord[0]).st; const vec4 redfilter = vec4(1.0, 0.0, 0.0, 0.0); const vec4 bluegreenfilter = vec4(0.0, 1.0, 0.7, 0.0); void main(void) { vec4 input0 = texture2D(bgl_RenderedTexture, texCoord); vec4 redrecord = input0 * redfilter; vec4 bluegreenrecord = input0 * bluegreenfilter; vec4 rednegative = vec4(redrecord.r); vec4 bluegreennegative = vec4((bluegreenrecord.g + bluegreenrecord.b)/2.0); vec4 redoutput = rednegative * redfilter; vec4 bluegreenoutput = bluegreennegative * bluegreenfilter; // additive 'projection" vec4 result = redoutput + bluegreenoutput; gl_FragColor = vec4(vec3(mix(input0, result, amount).rgb), 1.0); }
Code
uniform sampler2D bgl_RenderedTexture; const float amount = 1.0; vec2 texCoord = vec2(gl_TexCoord[0]).st; const vec4 redfilter = vec4(1.0, 0.0, 0.0, 0.0); const vec4 bluegreenfilter = vec4(0.0, 1.0, 0.7, 0.0); void main(void) { vec4 input0 = texture2D(bgl_RenderedTexture, texCoord); vec4 redrecord = input0 * redfilter; vec4 bluegreenrecord = input0 * bluegreenfilter; vec4 rednegative = vec4(redrecord.r); vec4 bluegreennegative = vec4((bluegreenrecord.g + bluegreenrecord.b)/2.0); vec4 redoutput = rednegative * redfilter; vec4 bluegreenoutput = bluegreennegative * bluegreenfilter; // additive 'projection" vec4 result = redoutput + bluegreenoutput; gl_FragColor = vec4(vec3(mix(input0, result, amount).rgb), 1.0); }
Code
uniform sampler2D bgl_RenderedTexture; const float amount = 1.0; vec2 texCoord = vec2(gl_TexCoord[0]).st; const vec4 redfilter = vec4(1.0, 0.0, 0.0, 0.0); const vec4 bluegreenfilter = vec4(0.0, 1.0, 0.7, 0.0); void main(void) { vec4 input0 = texture2D(bgl_RenderedTexture, texCoord); vec4 redrecord = input0 * redfilter; vec4 bluegreenrecord = input0 * bluegreenfilter; vec4 rednegative = vec4(redrecord.r); vec4 bluegreennegative = vec4((bluegreenrecord.g + bluegreenrecord.b)/2.0); vec4 redoutput = rednegative * redfilter; vec4 bluegreenoutput = bluegreennegative * bluegreenfilter; // additive 'projection" vec4 result = redoutput + bluegreenoutput; gl_FragColor = vec4(vec3(mix(input0, result, amount).rgb), 1.0); }
Code
uniform sampler2D bgl_RenderedTexture; const float amount = 1.0; vec2 texCoord = vec2(gl_TexCoord[0]).st; const vec4 redfilter = vec4(1.0, 0.0, 0.0, 0.0); const vec4 bluegreenfilter = vec4(0.0, 1.0, 0.7, 0.0); void main(void) { vec4 input0 = texture2D(bgl_RenderedTexture, texCoord); vec4 redrecord = input0 * redfilter; vec4 bluegreenrecord = input0 * bluegreenfilter; vec4 rednegative = vec4(redrecord.r); vec4 bluegreennegative = vec4((bluegreenrecord.g + bluegreenrecord.b)/2.0); vec4 redoutput = rednegative * redfilter; vec4 bluegreenoutput = bluegreennegative * bluegreenfilter; // additive 'projection" vec4 result = redoutput + bluegreenoutput; gl_FragColor = vec4(vec3(mix(input0, result, amount).rgb), 1.0); }
Code
uniform sampler2D bgl_RenderedTexture; const float amount = 1.0; vec2 texCoord = vec2(gl_TexCoord[0]).st; const vec4 redfilter = vec4(1.0, 0.0, 0.0, 0.0); const vec4 bluegreenfilter = vec4(0.0, 1.0, 0.7, 0.0); void main(void) { vec4 input0 = texture2D(bgl_RenderedTexture, texCoord); vec4 redrecord = input0 * redfilter; vec4 bluegreenrecord = input0 * bluegreenfilter; vec4 rednegative = vec4(redrecord.r); vec4 bluegreennegative = vec4((bluegreenrecord.g + bluegreenrecord.b)/2.0); vec4 redoutput = rednegative * redfilter; vec4 bluegreenoutput = bluegreennegative * bluegreenfilter; // additive 'projection" vec4 result = redoutput + bluegreenoutput; gl_FragColor = vec4(vec3(mix(input0, result, amount).rgb), 1.0); }
Code
uniform sampler2D bgl_RenderedTexture; uniform float timer; uniform float noise_amount; void main(void) { float noiseR = (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer)) * 43758.5453)); float noiseG = (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer*2)) * 43758.5453)); float noiseB = (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer*3)) * 43758.5453)); vec4 noise = vec4(noiseR,noiseG,noiseB,1.0); gl_FragColor = texture2D(bgl_RenderedTexture, gl_TexCoord[0].st) + (noise*noise_amount); }
Code
uniform sampler2D bgl_RenderedTexture; uniform float timer; uniform float noise_amount; void main(void) { float noiseR = (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer)) * 43758.5453)); float noiseG = (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer*2)) * 43758.5453)); float noiseB = (fract(sin(dot(gl_TexCoord[0].st ,vec2(12.9898,78.233)+timer*3)) * 43758.5453)); vec4 noise = vec4(noiseR,noiseG,noiseB,1.0); gl_FragColor = texture2D(bgl_RenderedTexture, gl_TexCoord[0].st) + (noise*noise_amount); }
Anton1987ru Дата: Вторник, 27.09.2011, 05:35 | Сообщение # 40
Космонавт
Группа: Команда SE
Российская Федерация
Сообщений: 56
Награды:
0
Статус: Offline
Добаляю ещё шейдеров
Code
uniform sampler2D bgl_RenderedTexture; uniform sampler2D bgl_DepthTexture; #define PI 3.14159265 const float blurclamp = 0.03; // max blur amount const float bias = 0.1; //aperture - bigger values for shallower depth of field const float treshold = 0.7; // highlight treshold const float brightness = 2.0; // highlight brightness const float saturation = 6.0; // highlight saturation const float contrast = 6.0; // highlight contrast const int samples = 6; //samples on the first ring const int rings = 8; //ring count uniform float focus; //focus value (0.0-1.0) vec4 sample(vec2 coo,float d) //processing the sample { vec3 col; // with chromatic aberration col.r = texture2D(bgl_RenderedTexture, coo - vec2(-0.04,-0.04)*d).r; col.g = texture2D(bgl_RenderedTexture, coo - vec2(0.04,-0.04)*d).g; col.b = texture2D(bgl_RenderedTexture, coo - vec2(0.0,0.04)*d).b; // without chromatic aberration //col.r = texture2D(bgl_RenderedTexture, coo).r; //col.g = texture2D(bgl_RenderedTexture, coo).g; //col.b = texture2D(bgl_RenderedTexture, coo).b; // processing bokeh highlight treshold, brightness, contrast and saturation float AvgLumR = 0.5; float AvgLumG = 0.5; float AvgLumB = 0.5; vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721); vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB); vec3 brtColor = col * brightness; vec3 intensity = vec3(dot(brtColor, LumCoeff)); vec3 satColor = mix(intensity, brtColor, saturation); vec3 conColor = mix(AvgLumin, satColor, contrast); float tresh = max(((col.r+col.g+col.b)*0.33)-treshold, 0.0); float brightamount = clamp(d * 30, 0.0, 1.0); //return vec4(col + (conColor*brightamount),1.0); return vec4(col+(conColor*tresh)*brightamount,1.0); //return vec4(col,1.0); } void main() { //getting blur amount for depth of field vec4 depth1 = texture2D(bgl_DepthTexture,gl_TexCoord[0].xy); float factor = (depth1.x - focus); vec2 blur = vec2 (clamp(factor * bias, -blurclamp, blurclamp)); vec4 col; float s; col += sample(gl_TexCoord[0].xy,blur); //middle sample // processing circles of samples for (int i = 0 ; i < rings; i += 1) { for (int j = 0 ; j < (samples*i); j += 1) { float step = PI*2.0 / (samples*i); float x = cos(j*step)*i*0.1; float y = sin(j*step)*i*0.1; col += sample(gl_TexCoord[0].xy + vec2(blur.x*x, blur.y*y),blur.x); s += 1.0; } } col = col/s; gl_FragColor.rgb = col; gl_FragColor.a = 1.0; }
Windows 7 x64 Core 2 quad Q8200 2.8 GHz 512mb Geforce 9800GTX+ 10 GB RAM ddr2
Сообщение отредактировал Anton1987ru - Вторник, 27.09.2011, 06:04
Angers Дата: Вторник, 27.09.2011, 15:14 | Сообщение # 41
Космонавт
Группа: Пользователи
Пират
Сообщений: 42
Награды:
0
Статус: Offline
У меня предложение по улучшению разработки движка. Владимир, ты бы мог сделать и прикрутить к движку функцию отправки отчёта о работе программы на различных ПК в двух вариациях, в последствии ты бы мог убрать (или оставить) данную функцию. Создай например отдельный эл.ящик для работы с аварийными отчётами, в движке зафиксируй темы отчетов, а в ящике настрой фильтр папки, вся корреспонденция будет приходить в аккуратном удобном для работы виде. 1) По собственному желанию, после завершения работы пользователя с программой. Возможно необходимо будет сделать форму для заполнения пользователем описания проблемы. - Полезно когда во время работы программы замечаются различные баги, которые не вызывают падения программы и пользователь может отправить тебе детальный отчет о работе программы. 2) При аварийном завершении программы. Отправка отчета инфо о железе компьютера и лог файл. - Полезно когда падает программа по тем или иным причинам, посмотрев инфо об ошибке можно оперативно её устранить.
Quad-Core AMD Phenom II X4 3456 MHz, RAM 4 Gb, GeForce GTX 460 2048 Мб, Windows 7 Pro x64 SP1
SpaceEngineer Дата: Понедельник, 03.10.2011, 15:30 | Сообщение # 42
Автор Space Engine
Группа: Администраторы
Российская Федерация
Сообщений: 5547
Награды:
55
Статус: Offline
Anton1987ru , спасибо, откуда вы их берёте? Можно ли приложить скриншоты с демонстрацией эффектов? Angers , да, это можно сделать. Только надо разобраться, как программно делать отправку письма.
Anton1987ru Дата: Вторник, 04.10.2011, 13:41 | Сообщение # 43
Космонавт
Группа: Команда SE
Российская Федерация
Сообщений: 56
Награды:
0
Статус: Offline
SpaceEngineer беру в основном из разных источников в гугле, демонстрация внизу под спойлером большинство - отсюда клик
Windows 7 x64 Core 2 quad Q8200 2.8 GHz 512mb Geforce 9800GTX+ 10 GB RAM ddr2
Сообщение отредактировал Anton1987ru - Вторник, 04.10.2011, 13:52
SHW Дата: Пятница, 18.11.2011, 15:04 | Сообщение # 44
Строитель Миров
Группа: Команда SE
Нидерланды
Сообщений: 618
Награды:
10
Статус: Offline
Возможно в порядке бреда (может это и так есть), но возникла идея, как можно уменьшить количество используемой видео памяти под текстуры планет, когда камера расположена близко к поверхности - использовать не квадратные текстуры патчей, а прямоугольные. Дело в том, что когда патч находится далеко от камеры, а камера при этом расположена низко над поверхностью, получается, что патч повёрнут почти перпендикулярно плоскости проекции, и выглядит очень сжатым. То есть размер по одной из координат получается больше, чем по другой в разы. А значит и использовать для него квадратную текстуру очень не рационально. В этом случае разрешением по координате, которая уходит от камеры можно пожертвовать без каких либо визуальных проблем. Доработка при этом потребуется тоже вроде как не значительная. Достаточно с каждым патчем хранить размер текущей сгенерированной текстуры, или даже можно хранить несколько версий с разными разрешениями по координатам. В этом случае, та, что в данный момент не требуется просто вытеснится из кеша, а та, что нужна - останется. Теоретически, таким образом можно будет уменьшить потребление видеопамяти планетами в разы.
Win7 Pro x64 Intel Core2Quad 2.5GHz 4GiB RAM NVidia GForce 9800 1 GiB
GV_FiQst Дата: Воскресенье, 20.11.2011, 21:07 | Сообщение # 45
Строитель Миров
Группа: Команда SE
Украина
Сообщений: 1062
Награды:
3
Статус: Offline
Нашел алгоритм «diamond-square» для построения фрактальных ландшафтов. я в этом мало чего смыслю но всеравно спрошу у SE лутше или хуже алгоритм создание ландшафтов?
AMD Phenom II X2 555 3200 MHz; RAM 4GB 1333 Hz; ATI Radeon HD 5670 1024 Mb; ОС Win 7 tabulorasa edition 32 bit
Сообщение отредактировал GV_FiQst - Воскресенье, 20.11.2011, 21:07