Контур сферы

Версия Minecraft
1.7++

Icosider

Kotliner
Администратор
3,603
99
664
Добрый день, делаю второй щит в виде сферы, и понадобилось сделать контур для неё, а цент оставить прозрачным. Примерный пример, того что мне надо есть на скрине ниже. Как такое сделать?
[img=721x450]https://i.imgur.com/qhCfio2l.jpg[/img]
 
Решение
Oldestkon написал(а):
Гугли Fresnel Effect.
Грубо говоря, тебе нужно написать шейдер, который будет менять прозрачность пикселя в зависимости от нормали (в пространстве камеры).
Формула коэффициента прозрачности (или непрозрачности, непомню) для каждого пикселя будет уровня dotProduct(векторОтКамерыДоПикселя, векторНормали). Мб придется возвести в степень, поиграйся.
Вектора должны быть нормализованными.
Вектор нормали возьмешь из вершинного шейдера, он просчитается для нужного пикселя исходя из нормалей вершин сферы. Второй - это тупо координаты пикселя в пространстве (камеры).

Шейдер должен подключаться (glUseProgram) перед отрисовкой твоей сферы, и выключаться после. Загрузка находится быстрым гуглением (lwjgl shader loader).

Без шейдера...
7,099
324
1,510
Ну по другому окрашивай те полигоны, которые относительно пользователя "по краям"
 
1,990
18
105
Гугли Fresnel Effect.
Грубо говоря, тебе нужно написать шейдер, который будет менять прозрачность пикселя в зависимости от нормали (в пространстве камеры).
Формула коэффициента прозрачности (или непрозрачности, непомню) для каждого пикселя будет уровня dotProduct(векторОтКамерыДоПикселя, векторНормали). Мб придется возвести в степень, поиграйся.
Вектора должны быть нормализованными.
Вектор нормали возьмешь из вершинного шейдера, он просчитается для нужного пикселя исходя из нормалей вершин сферы. Второй - это тупо координаты пикселя в пространстве (камеры).

Шейдер должен подключаться (glUseProgram) перед отрисовкой твоей сферы, и выключаться после. Загрузка находится быстрым гуглением (lwjgl shader loader).

Без шейдера можно обойтись, скорее всего моделькой сферы у которой по краям текстура прозрачная, и которая всегда поворачивается "лицом" к игроку, но это будет выглядеть заметно хуже.
 
4,045
63
645
"это тупо координаты пикселя в пространстве"
Ну-ну... Я как ни парился, так и не понял, как же это в шейдере найти тупо координаты пикселя...
Да и в шейдерах майновских так ничего понять не смог...
 
1,990
18
105
В шейдере их просто так не найдешь, там либо координаты в пространстве модели, либо спроецированные на плоскость.
Тебе нужны мировые (model-matrix трансформация), топик-стартеру в пространстве камеры (modelview).

Надо отдельно передавать различные матрицы (модели-вида и проекции), чтобы получать координаты в нужном пространстве.
Для этого, к сожалению, скорее всего, ещё придется написать свой стек матриц.
Подробнее тут.
http://stackoverflow.com/questions/4899555/glsl-how-to-get-pixel-x-y-z-world-position

Хотя вроде были способы проще, мож кто подскажет, но я сходу не вспомню, а думать лень.
 

Icosider

Kotliner
Администратор
3,603
99
664
Oldestkon написал(а):
многабукав...

Хотя вроде были способы проще, мож кто подскажет, но я сходу не вспомню, а думать лень.

Вчера копался в исходниках ведьмака(игра на скрине) и нашёл очень интересную вещь, разработчики данной игры рендерят сферу как модель, а не как что-то абстрактное.
 
164
1
4
Oldestkon написал(а):
Гугли Fresnel Effect.
Грубо говоря, тебе нужно написать шейдер, который будет менять прозрачность пикселя в зависимости от нормали (в пространстве камеры).
Формула коэффициента прозрачности (или непрозрачности, непомню) для каждого пикселя будет уровня dotProduct(векторОтКамерыДоПикселя, векторНормали). Мб придется возвести в степень, поиграйся.
Вектора должны быть нормализованными.
Вектор нормали возьмешь из вершинного шейдера, он просчитается для нужного пикселя исходя из нормалей вершин сферы. Второй - это тупо координаты пикселя в пространстве (камеры).

Шейдер должен подключаться (glUseProgram) перед отрисовкой твоей сферы, и выключаться после. Загрузка находится быстрым гуглением (lwjgl shader loader).

Без шейдера можно обойтись, скорее всего моделькой сферы у которой по краям текстура прозрачная, и которая всегда поворачивается "лицом" к игроку, но это будет выглядеть заметно хуже.

Я короче погуглил, нашел ЭТО и тут даже есть готовый шейдер, но для Юнити. Я в шейдерах не силён, но вроде переписал, получилось так ->
Вершинный шейдер:
Код:
#version 120

varying vec3 position;
varying vec3 normal;

void main()
{
    gl_Position = ftransform();

    position = (gl_ModelViewMatrix * gl_Vertex).xyz;
    normal = normalize(gl_NormalMatrix * gl_Normal);
}
Фрагментный шейдер:
Код:
#version 120

varying vec3 position;
varying vec3 normal;

void main()
{
    vec4 rimColor = vec4(1.0, 1.0, 1.0, 1.0);
    float scale = 1.0;
    vec3 cameraPos = -position;
    vec3 ray = normalize(position - cameraPos);
    float refFactor = max(0.0, min(1.0, scale * pow(1.0 + dot(ray, normal), 1.4)));

    gl_FragColor = mix(vec4(1.0, 1.0, 1.0, 0.0), rimColor, refFactor);
}
 Результат... ну, не очень, не так как на картиночке в статье:
0cmms9B.png
 

Icosider

Kotliner
Администратор
3,603
99
664
nikita488 написал(а):
Oldestkon написал(а):
Гугли Fresnel Effect.
Грубо говоря, тебе нужно написать шейдер, который будет менять прозрачность пикселя в зависимости от нормали (в пространстве камеры).
Формула коэффициента прозрачности (или непрозрачности, непомню) для каждого пикселя будет уровня dotProduct(векторОтКамерыДоПикселя, векторНормали). Мб придется возвести в степень, поиграйся.
Вектора должны быть нормализованными.
Вектор нормали возьмешь из вершинного шейдера, он просчитается для нужного пикселя исходя из нормалей вершин сферы. Второй - это тупо координаты пикселя в пространстве (камеры).

Шейдер должен подключаться (glUseProgram) перед отрисовкой твоей сферы, и выключаться после. Загрузка находится быстрым гуглением (lwjgl shader loader).

Без шейдера можно обойтись, скорее всего моделькой сферы у которой по краям текстура прозрачная, и которая всегда поворачивается "лицом" к игроку, но это будет выглядеть заметно хуже.

Я короче погуглил, нашел ЭТО и тут даже есть готовый шейдер, но для Юнити. Я в шейдерах не силён, но вроде переписал, получилось так ->
Вершинный шейдер:
Код:
#version 120

varying vec3 position;
varying vec3 normal;

void main()
{
    gl_Position = ftransform();

    position = (gl_ModelViewMatrix * gl_Vertex).xyz;
    normal = normalize(gl_NormalMatrix * gl_Normal);
}
Фрагментный шейдер:
Код:
#version 120

varying vec3 position;
varying vec3 normal;

void main()
{
    vec4 rimColor = vec4(1.0, 1.0, 1.0, 1.0);
    float scale = 1.0;
    vec3 cameraPos = -position;
    vec3 ray = normalize(position - cameraPos);
    float refFactor = max(0.0, min(1.0, scale * pow(1.0 + dot(ray, normal), 1.4)));

    gl_FragColor = mix(vec4(1.0, 1.0, 1.0, 0.0), rimColor, refFactor);
}
 Результат... ну, не очень, не так как на картиночке в статье:
0cmms9B.png
Спасибо и если не сложно, кинь всю свою репозиторию, где у тебя сам шейдер и т.п., хочу глянуть живой пример.
 
164
1
4
Oldestkon написал(а):
В шейдере их просто так не найдешь, там либо координаты в пространстве модели, либо спроецированные на плоскость.
Тебе нужны мировые (model-matrix трансформация), топик-стартеру в пространстве камеры (modelview).

Надо отдельно передавать различные матрицы (модели-вида и проекции), чтобы получать координаты в нужном пространстве.
Для этого, к сожалению, скорее всего, ещё придется написать свой стек матриц.
Подробнее тут.
http://stackoverflow.com/questions/4899555/glsl-how-to-get-pixel-x-y-z-world-position

Хотя вроде были способы проще, мож кто подскажет, но я сходу не вспомню, а думать лень.

Там написано что нужно трансформировать камеру через glLoadIdentity()[font=Arial,], [/font]glTranslate(), а какие значения то в glTranslate? Я нашел в EntityRenderer метод setupCameraTransform и попробовал в RenderWorldLastEvent'е сделать типа так:
Код:
GlStateManager.loadIdentity();
EntityRenderer.setupCameraTransform(partialTicks, 0); //На самом деле нужна рефлексия, все дела
GlStateManager.getFloat(GL11.GL_MODELVIEW_MATRIX, viewMatrixBuffer);

Но если я после этого сбрасываю матрицу и трансформирую модель вот так:
Код:
GlStateManager.loadIdentity();
GlStateManager.translate(-interpPlayerPosX, 16 - interpPlayerPosY, -interpPlayerPosZ);
GlStateManager.getFloat(GL11.GL_MODELVIEW_MATRIX, modelMatrixBuffer);

То модель начинает двигаться в зависимости от моего положения.
 
1,990
18
105
nikita488 написал(а):
Там написано что нужно трансформировать камеру через glLoadIdentity()[font=Arial,], [/font]glTranslate(), а какие значения то в glTranslate? Я нашел в EntityRenderer метод setupCameraTransform и попробовал в RenderWorldLastEvent'е сделать типа так:
Код:
GlStateManager.loadIdentity();
EntityRenderer.setupCameraTransform(partialTicks, 0); //На самом деле нужна рефлексия, все дела
GlStateManager.getFloat(GL11.GL_MODELVIEW_MATRIX, viewMatrixBuffer);

Но если я после этого сбрасываю матрицу и трансформирую модель вот так:
Код:
GlStateManager.loadIdentity();
GlStateManager.translate(-interpPlayerPosX, 16 - interpPlayerPosY, -interpPlayerPosZ);
GlStateManager.getFloat(GL11.GL_MODELVIEW_MATRIX, modelMatrixBuffer);

То модель начинает двигаться в зависимости от моего положения.

Не сбрасывать матрицу после setupCameraTransform? Ты ж теряешь поворот камеры. Смещение вроде ок, если правильно вычисляется.

И вообще - то, что я описывал в твоей цитате - способ получить нужные матрицы в шейдере не используя deprecated функционал (на самом деле я прост забыл какие встроенные переменные там доступны из шейдера), так что навряд ли оно сильно нужно кому-то здесь, разве что для самообразования.
 
Сверху